1
var Main = function(){};
    Main.prototype = {
        'times' : 0,
        'request': function(){},
        ...
    };

var SubA = function(){};
    SubA.prototype = new Main() // same with Object.create(Main.prototype);
    SubA.prototype.constructor = SubA;

var SubB = function(){};
    SubB.prototype = new Main() // same with Object.create(Main.prototype);
    SubB.prototype.constructor = SubB;

Now:

var sub_a = new SubA();
    sub_a.times = 1;

var sub_b = new SubB();
   // Here sub_b.times is already 1, how?

When I change the properties of sub classes, properties of Main are also changing, shouldn't it stay at 0?

NestedWeb
  • 1,657
  • 2
  • 15
  • 31
  • 2
    It stays at 0 for me just using Chrome console? – Monica Olejniczak Mar 02 '15 at 15:52
  • 1
    `sub_a.times = 1;` will never (!) change the `sub_b.times`, unless `sub_a === sub_b`. This has nothing to do with prototypes. *Assigning* to a property always adds or changes the property on the objects itself (whether it exists in the prototype chain or not). – Felix Kling Mar 02 '15 at 16:25
  • 1
    Related: [Javascript object members that are prototyped as arrays become shared by all class instances](http://stackoverflow.com/q/4425318/218196) – Felix Kling Mar 02 '15 at 17:42

1 Answers1

2

As the comments have already pointed out, your exact question is incorrect and, in fact, sub_b.times is still 0. Perhaps something else is going on in your code.

I will take a guess as to what might be going on outside of your specific question and explain primitive vs. reference types through the code below. Notice the difference between storing times and count on our prototype:

var Main = function(){};
Main.prototype = {
  'times' : 0,
  'count': {value: 0}
};

var SubA = function(){};
  SubA.prototype = new Main();
  SubA.prototype.constructor = SubA;

var SubB = function(){};
  SubB.prototype = new Main();
  SubB.prototype.constructor = SubB;

var subA = new subA();
var subB = new subB();

Our times property is a primitive value and when we incrementing the primitive value of subA.times has no effect on subB and vice-versa:

console.log(subA.times); // 0
console.log(subB.times); // 0

subA.times = 1;
console.log(subA.times); // 1
console.log(subB.times); // 0

subB.times = 100;
console.log(subA.times); // 1
console.log(subB.times); // 100

Our count property, however, is an object storing a value primitive. An object is a reference type and, in short, means that subA.count and subB.count reference the same object in memory and if we change that object's properties it will be reflected in both. If I had to take a guess, this is likely the case that might be happening in your actual implementation.

console.log(subA.count.value); // 0
console.log(subB.count.value); // 0

subA.count.value = 1;
console.log(subA.count.value); // 1
console.log(subB.count.value); // 1

subB.count.value = 100;
console.log(subA.count.value); // 100
console.log(subB.count.value); // 100

One final note: If we decide to re-assign the count property of one of our instances to a new object then it will no longer reference the same object and would be separate:

subA.count = {value: -1}; // New object
console.log(subA.count.value); // -1 (new object value)
console.log(subB.count.value); // 100 (old value from above)

subB.count.value = 99;
console.log(subA.count.value); // -1
console.log(subB.count.value); // 99
rgthree
  • 7,217
  • 17
  • 21