1

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
1
  • Because your line this.counter += amount is actually doing this.counter = Dog.Prototype.counter + 1 Commented Sep 20, 2013 at 19:28

2 Answers 2

3

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";
Sign up to request clarification or add additional context in comments.

3 Comments

Good answer; you should speak to why the array letters remains shared across instances of Dog.
@NickHusher I've edited in an explanation for letters too, as requested. Though I don't feel there is too much to say about it, as the action performed is entirely different.
Thank you Paul! I suspected the instance vs. prototype scope on the counter but the array was throwing me off. I didn't think about the fact that I'm calling a function on the array vs setting it directly.
0

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;
    },

    ...

};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.