0

I think that I did not understand the whole prototype flow, I have this problem:

function SomeO() {};
SomeO.prototype.arr = [];
SomeO.prototype.str = "";

var s1 = new SomeO();
var s2 = new SomeO();

s1.str+="1"
console.log(s2) // "" OK

s1.arr.push(1)
console.log(s2) // [1] WHY???

Why when I add an item to an array in one object it has the same array instance?

deceze
  • 510,633
  • 85
  • 743
  • 889
Shai Kimchi
  • 746
  • 1
  • 4
  • 22

4 Answers4

2

That's because objects are shared by reference by all the instances of your "SomeO" object, in this case your "arr" attribute, and things like strings or numbers are shared by value, so the modification of the string will not affect the values of other instances.

so in that case is normal to get that result.

function SomeO() {};
SomeO.prototype.arr = [];
SomeO.prototype.str = "chimichangas";

var s1 = new SomeO();
var s2 = new SomeO();

s1.str+="1"
console.log(s1.str); // "chimichangas1" OK because is by value
console.log(s2.str); // "chimichangas"  OK because is by value

s1.arr.push(1);
console.log(s2.arr); // [1] WHY??? because is by reference

And if you don't want to share the array you should do something like.

function SomeO() {
  this.arr = [];
};
SomeO.prototype.str = "";

var s1 = new SomeO();
var s2 = new SomeO();

s1.str+="1"
console.log(s1.str); // "1" OK
console.log(s2.str); // ""  OK

s1.arr.push(1);
console.log(s1.arr); // [1] Ok
console.log(s2.arr); // []  Ok
Jberivera
  • 36
  • 2
  • I understand, but by putting the array initialisation inside the constructor is somehow mskes the whole ptototype concept irrelevent. – Shai Kimchi Mar 03 '16 at 07:34
0

Because both instances share the same [[Prototype]](the Object assigned to SomeO.prototype), the also share the same Array in SomeO.prototype.arr.

You can check it yourself:

s1.arr === s2.arr

To circumvent this, you could define the array (and all other objects you might need) in the constructor instead:

function SomeO() {
    this.arr = [];
    this.obj = {}; // define all arrays and objects in the constructor if they need to be separate
}
nils
  • 25,734
  • 5
  • 70
  • 79
0

Because that's how you defined the array: you create one array object on the prototype which is shared between all instances. Typically you'll only want to put functions and constant values on the prototype. Every instance property needs to be created inside the constructor:

function SomeO() {
    this.arr = [];
}
deceze
  • 510,633
  • 85
  • 743
  • 889
0

When you reference a property of an object (e.g. s1.arr), it first checks if the property exists on the object, if it does, it returns it, if it doesn't, it falls back to the object's prototype.

When you do s1.str += "1", which is equivalent to s1.str = s1.str + "1", you're setting the str property on the object itself, the prototype's str property doesn't change. s1.str will return the new string from s1, and s2.str will fall back to prototype.str.

          s1's str   s2's str   prototype's str   s1.str            s2.str
before:   -          -          ""                "" (from proto)   "" (from proto)
after:    "1"                   ""                "1" (from own)    "" (from proto)

When you do s1.arr.push(1) you get s1.arr from the prototype, and you change its value. You never set the arr property on s1.

          s1's arr   s2's arr   prototype's arr   s1.arr            s2.arr
before:   -          -          []                [] (from proto)   [] (from proto)
after:    -          -          [1]               [1] (from proto)  [1] (from proto)
Leventix
  • 3,789
  • 1
  • 32
  • 41