I\'m trying to get my head around this black art called JavaScript - and, I must admit, pretty excited about it. I\'ve been looking at code examples, mainly from \"easeljs\"
The value on a prototype has a key behaviour that is different from a property set directly on the instance. Try this:
// Create a constructor
function A() {}
// Add a prototype property
A.prototype.name = "Freddy";
// Create two object instances from
// the constructor
var a = new A();
var b = new A();
// Both instances have the property
// that we created on the prototype
console.log(a.name); // Freddy
console.log(b.name); // Freddy
// Now change the property on the
// prototype
A.prototype.name = "George";
// Both instances inherit the change.
// Really they are just reading the
// same property from the prototype
// rather than their own property
console.log(a.name); // George
console.log(b.name); // George
This would not possible without prototypical inheritance.
You can test whether the property is the instances property or the prototype property using the hasOwnProperty
method.
console.log(a.hasOwnProperty("name")); // false
An instance can override the prototype
value.
b.name = "Chris";
console.log(b.hasOwnProperty("name")); // true
console.log(a.name); // George
console.log(b.name); // Chris
And return to the prototype
value.
delete b.name;
console.log(b.hasOwnProperty("name")); // false
console.log(b.name); // George
This is a powerful part of prototypical inheritance.
In the other pattern:
function A() {
this.name = "George";
}
The this.name
variable is declared again with every new instance.
It makes some sense to have methods as functions declared on the prototype. Rather than the function definition being re-declared on every instance, all instances can share a single function.
In terms of variables, rather than functions, the prototype can possibly be used for default values in the case that an instance does not set its own value.
The code in a fiddle
Other answers have already explained the difference between prototype vs instance properties.
But just to add to the answer, let's break down your code snippet:
(function(){ // <------- 1
// constructor
function MyCircle(radius){ // <------- 2
this.radius = radius; // <------- 2.1
}
MyCircle.prototype.radius; // <------- 3
this.area = function(){ // <------- 4
return 3.14*this.radius*this.radius;
};
window.MyCircle = MyCircle; // <------- 5
}());
IIFE
which acts as a scope container for the inner codeMyCircle
using a constructor pattern (but observe that it never gets "constructed" so should probably get rid of the capital letter since it's misleading)
radius
instance property on the invoked objectradius
property on MyCircle
function's prototype
which doesn't exist so evaluates to undefined
area
instance property on the global window object and assigning it a function expressionMyCircle
instance property on a window
object and assigning to it the MyCircle
functionSummary: It seems like it's creating an area
and MyCircle
properties on the global window
object, and when MyCircle
is invoked it creates an additional radius
property.
Usage: MyCircle should be invoked before area since area relies on MyCircle initialising the radius:
window.MyCircle(10);
window.area(); // evaluates to 314
A value stored on the prototype provides a default value for that property.
If you subsequently write a value to that property, the instance will acquire that new value, hiding the value that's on the prototype, which will be left intact.
In the context of the code you've now added to the question:
MyCircle.prototype.radius;
does absolutely nothing. It's a no-op - it attempts to read that property and then discards the result.
Yeah, I agree the prototype can be used for default values of properties (variables). The constructor function doesn't need to declare a property; it may be done conditionally.
function Person( name, age ) {
this.name = name;
if ( age ) {
this.age = age;
}
}
Person.prototype.sayHello = function() {
console.log( 'My name is ' + this.name + '.' );
};
Person.prototype.sayAge = function() {
if ( this.age ) {
console.log( 'I am ' + this.age + ' yrs old!' );
} else {
console.log( 'I do not know my age!' );
}
};
Person.prototype.age = 0.7;
//-----------
var person = new Person( 'Lucy' );
console.log( 'person.name', person.name ); // Lucy
console.log( 'person.age', person.age ); // 0.7
person.sayAge(); // I am 0.7 yrs old!
See how Lucy's age
is conditionally declared and initialized.