Search code examples
javascriptcomputed-properties

Why is my computed property not effective after Object.assign?


I stumbled upon code similar to this in modern JavaScript:

let obj = {
  data: {number: 9},
  set prop(p) {
    this.data = p;
  },
  get prop() {
    return this.data;
  }
};

obj = Object.assign({}, obj, {
  data: {number: 2}
});

console.log('obj.data === obj.prop ', obj.data === obj.prop);
console.log('obj.data.number === obj.prop.number ', obj.data.number === obj.prop.number);

Any modification is done outside of the computed property, as if there were none.

I was expecting the computed property to still exist.

Is there a way to preserve the computed property after a call to Object.assign? Thanks.


Solution

  • If you look at the result of the new object created by object.assign you will see that it no longer has getter/setter, but has a property prop. object.assign doesn't copy the getter/setter functions over but instead calls [[get]] and makes a new property.

    MDN describes it:

    It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties versus just copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters.

    So assign() merges an object with a prop property together with an object with a data property and you get both:

    let obj = {
      data: {
        number: 9
      },
    
      set prop(p) {
        this.data = p;
      },
    
      get prop() {
        return this.data;
      }
    
    };
    
    obj = Object.assign({}, obj, {
      data: {
        number: 2
      }
    });
    
    // it has a data and a prop property -- they are not the same:
    console.log(obj)