Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prototype chain using Object.assign and descriptors

Tags:

javascript

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?

like image 947
turkus Avatar asked Aug 25 '26 21:08

turkus


1 Answers

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 -------------------------^^^^

Also note that Object.assign copies the value of a from firstObject to that new object, not the property descriptor for it. So the a property on secondObject is just a simple property, not an accessor.

Here's a snippet with the change above, and showing the descriptors on each of the objects at the end:

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(
  "firstObject's a descriptor:",
  Object.getOwnPropertyDescriptor(firstObject, "a")
);
console.log(
  "secondObject's a descriptor:",
  Object.getOwnPropertyDescriptor(secondObject, "a")
);

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.

like image 182
T.J. Crowder Avatar answered Aug 29 '26 20:08

T.J. Crowder



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!