1

In the Javascript code below I create 2 instances of Person (p1 and p2).

When changing the name of p1, only the name of p1 is changed (and not the name of p2). This is exactly what I expect.

But when changing p1.sizes.width and then checking the value of p2.sizes.width, it appears that p1.sizes.width is equal to p2.sizes.width.

Why?

var Person = {
  name: '',
  sizes: {width: {type:'size', value:undefined}, height: {type:'size', value:undefined}}
}

var p1 = Object.create(Person);
var p2 = Object.create(Person);

p1.name = "Alice";
p2.name = "Bob";

console.log(p1.name === "Alice") // true
console.log(p2.name === "Bob") // true

p1.sizes.width=20;

console.log(p1.sizes.width === 20) // true
console.log(p2.sizes.width === 20) // true (but I would had expected false...?!)
Mikou
  • 579
  • 1
  • 8
  • 17

2 Answers2

1

You're creating a delegation chain to the same object as opposed to instantiating new versions of Person each time. This means that when the JIT compiler looks for the property sizes (which is undefined on the p1/p2 object) - it goes up to the next object in the delegation chain - in this case Person - so it will then modify .sizes.width. The reason why it doesn't matter on the names property is that you are overwriting that property on the individual instance. If you want separate instantiations then use the new keyword ie:

var Person = function(){
  this.name = '',
  this.sizes = {width: {type:'size', value:undefined}, height: {type:'size', value:undefined}}
}

var p1 = new Person();
var p2 = new Person();

p1.name = "Alice";
p2.name = "Bob";

console.log(p1.name === "Alice") // true
console.log(p2.name === "Bob") // true

p1.sizes.width=20;

console.log(p1.sizes.width === 20) // true
console.log(p2.sizes.width === 20) // false

You can read more here and here

Community
  • 1
  • 1
0

Reading a property of any javascript object looks for the named property in the local properties of the object first. If not found searching proceeds to look at objects in the prototype chain one by one, looking for a property of the same name, until it finds one or the prototype chain has been exhausted. If found, the value of the property in the prototype chain is returned.

Writing a property of a javascript object always writes it as a local property - the value of a same named property in the prototype chain is not updated.

So...

Writing the unadorned property 'name' of an object returned by Object.create(Person); writes it in local properties, one value in p1, another in p2.

Writing to p1.sizes.width=20; however first needs to find a reference to object p1.sizes, by attempting to read it from p1. The read returns the sizes property of Person, found in the prototype chain, which is the same value for both p1.sizes and p2.sizes. Since they are the same object, writing to them is shared by p1 and p2.

Reading properties - searches the prototype chain if needed.

Writing properties - always writes to local properties.

Community
  • 1
  • 1
traktor
  • 17,588
  • 4
  • 32
  • 53