Reputation: 13
Can anybody help me understand why the "counter" property seems to get reset on every new instance? I expected it to work like the "letters" property, which is shared across all instantiated objects.
I came across this while putting together some sample code as to why prototype properties shouldn't be used this way unless they are intended to be static.
Sample Code:
var Dog = function() {
this.initialize.apply(this, arguments);
};
Dog.prototype = {
counter : 2,
letters : [ 'a', 'b', 'c' ],
initialize : function(dogName) {
this.dogName = dogName;
},
add : function(amount) {
this.counter += amount;
},
arr : function(char) {
this.letters.push(char);
}
};
var fido = new Dog("fido");
fido.add(1);
fido.arr('d');
console.log(fido.counter); // 3, as expected
console.log(fido.letters.toString()); // ABCD, as expected
var maxx = new Dog("maxx");
maxx.add(1);
maxx.arr('e');
console.log(maxx.counter); // 3, Unexpected, Why isn't this 4?
console.log(maxx.letters.toString()); // ABCDE, as expected
Upvotes: 1
Views: 50
Reputation: 66364
This is due to the line
this.counter += amount;
What happens? this.counter
doesn't find property counter on the instance, so it takes it from the prototype, but when it comes to setting, it sets it on the instance
var fido = new Dog("fido");
console.log(fido.hasOwnProperty('counter')); // false
fido.add(1);
console.log(fido.hasOwnProperty('counter')); // true
Remember it is shorthand for
this.counter = this.counter + amount;
/* ↑ ↑
instance |
prototype */
As for letters, that is working as expected because push
is happening on the Object in the prototype - you're not setting a new instance variable. If you were setting an instance variable, it may still work because Objects are assigned to variables by reference, i.e.
var a = {}, b = a;
b.foo = 'bar';
a.foo; // "bar";
Upvotes: 3
Reputation: 2118
When you say this.counter += amount
in add
, this
refers to the object that add
was called on (in this case fido or maxx). In this case the += operator reads from the inherited value because there is no local value for counter
and the writes to a new local value. Because fido or maxx now have their own counter properties the prototype covered up. Try the following:
Dog.prototype = {
...
add : function(amount) {
Dog.prototype.counter += amount;
},
...
};
Upvotes: 0