turkus turkus - 2 months ago 7
Javascript Question

Prototype chain using Object.assign and descriptors

Let's consider this situation:



var firstObject = {
set a(val) {
this._a_ = val;
},
get a() {
return this._a_;
}
}

var secondObject = Object.assign(firstObject);

secondObject.a = 3;

console.log(secondObject.a); // 3
console.log(firstObject.a); // 3

console.log(secondObject.hasOwnProperty('a')); // true
console.log(firstObject.hasOwnProperty('a')); // true





Why both
firstObject
and
secondObject
returns 3?
How prototype chaining works here?

Answer

Because the first argument to Object.assign is the object to assign to. Then Object.assign returns a reference to that object. It assigns from subsequent arguments, but you aren't supplying any. So the end result is that FirstObject and SecondObject just point to the same object:

var FirstObject = {
  set a(val) {
  	this._a_ = val;
  },
  get a() {
  	return this._a_;
  }
}

var SecondObject = Object.assign(FirstObject);
console.log("Same object? " + (FirstObject === SecondObject));

You wanted:

var SecondObject = Object.assign({}, FirstObject);
// Note -------------------------^^^^

var FirstObject = {
  set a(val) {
  	this._a_ = val;
  },
  get a() {
  	return this._a_;
  }
}

var SecondObject = Object.assign({}, FirstObject);

SecondObject.a = 3;

console.log(SecondObject.a); // 3
console.log(FirstObject.a);  // undefined

FirstObject.a = 42;
console.log(FirstObject.a);  // 42
console.log(SecondObject.a); // still 3

console.log(SecondObject.hasOwnProperty('a')); // true
console.log(FirstObject.hasOwnProperty('a')); // true


Also note that as Mister Epic pointed out, there is no real use of the prototype chain here at all. FirstObject has an own property a, and after the copy, so does SecondObject. SecondObject doesn't inherit from FirstObject or anything like that; Object.assign copies properties.