Why are getter/setter no longer working after copying an object with the spread syntax?

In the following snippet, the spread syntax works in a manner that I don't quite understand:

let obj = {
  set setName(name){
    obj.name = name
  },
  get myName() {
    return obj.name
  }
}
    
obj.setName = 'Jon Doe'

let spread_obj = {...obj}
spread_obj.setName = 'Marion Luke'
console.log('spread_obj name', spread_obj.myName) // spread_obj name Jon Doe 

let create_obj = Object.create(obj)
create_obj.setName = 'Marion Luke'
console.log('create_obj name', create_obj.myName) // create_obj name Marion Luke

Spreading an object does not copy getter and setter methods - rather, the spread operation only gets the property (that is, it calls the getter, if there is one), and assigns the result to the resulting object (the spread_obj, here), just like a normal object, without any getters or setters. You can see this if you put log statements inside the setter and getter. The resulting spread_obj has a setName property of undefined because setName is only a setter method, which doesn't return anything.

let obj = {
  set setName(name){
    console.log('setting ' + name);
    this.name = name
  },
  get myName() {
    console.log('getting');
    return this.name
  }
}

obj.setName = 'Jon Doe'
console.log('About to spread');
let spread_obj = {...obj}
console.log('Done spreading. spread_obj contents is:');
console.log(spread_obj);
spread_obj.setName = 'Marion Luke' // No "setting" log statement

Spread syntax, Spread syntax allows an iterable such as an array expression or string to be an object expression to be expanded in places where zero or more key-value When calling a constructor with new it's not possible to directly use an Therefore, it may be unsuitable for copying multidimensional arrays, as the  There's a lot of old tickets about this. Basically Coffeescript only implements features that work in all the major browsers. The current versions of IE don't support it, so don't expect this feature to appear until at least after IE 8 is no longer used by a substantial number of people.

In addition to @CertainPerformances explanation, I would add that the behavior seems more sensible when using the getters/setters a more traditionally by having one name for both get and set.

For example when your object looks like this, everything works a little better (at least on the surface):

let obj = {
  set name(name){        // setter and getter are accessed with the same property
    this._name = name
  },
  get name() {
    return this._name
  }
}

obj.name = 'Jon Doe'
let spread_obj = {...obj}
spread_obj.name = 'Marion Luke'

// this seems more expected
console.log('spread_obj name', spread_obj.name)

// but this is still a little strange because
// Jon Doe is still there
console.log(spread_obj)

ES2018: Rest/Spread Properties, At the moment, this operator only works for Array destructuring and in similar to the spread operator (we'll compare them in more detail later). Cloning the enumerable own properties of an object obj : including getters and setters. Object.assign() also triggers own setters during copying, it does not  Spreading an object does not copy getter and setter methods - rather, the spread operation only gets the property (that is, it calls the getter, if there is one), and assigns the result to the resulting object (the spread_obj, here), just like a normal object, without any getters or setters. You can see this if you put log statements inside the

Master Javascript's New, Cutting-Edge Object Spread Operator, With Node v8.0.0 introducing object rest and spread functionality behind the harmony When duplicate properties clash, the order determines the outcome. that value is put directly on the target object without the getter or setter. Learn how Array.map and Array.filter work by writing them yourself. More from codeburst  2. The initialisation patterns you showed with js and C# has nothing to do with constructors: what you did in js is passed a single argument, and what you did in C# is a syntax shugar that calls geters and setters behind the scenes, and java does not have the geter-setter shugar like C# does. – Ben Feb 2 '16 at 17:48

spread operator doesn't use set function to assign property · Issue , assign and see it invokes setters and getters, but doesn't pass them along. I'll simply need to use another method of copying the object. I think my  A default getter simply returns the field, and is named getFoo if the field is called foo (or isFoo if the field's type is boolean ). A default setter is named setFoo if the field is called foo, returns void, and takes 1 parameter of the same type as the field. It simply sets the field to this value. The generated getter/setter method will be

Spread operator does not call property getters · Issue #26547 , GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together. Sign up. @DanielKaplan: the point is that calling getters and setters is in most cases the right thing to do, and only in specific situations not. However, in real world code, when you change an existing getter/setter-implementation later to introduce some intentional side effects, you will most probably have to check every call to the getter or setter inside the class, and also every direct access to

The tale of three dots in Javascript, I'll explain how the three dots work and show the most common with the concat method, but why not use the spread operator again? Arguments in Javascript are array-like objects. Copying works the same way as with arrays. syntax; all the above examples can be tried in browser console while  Just passing by to point out to @NemanjaTrifunovic that that Why getter and setter methods are evil article is quite old, is about java and underlines a java weakness: the weakness of not having properties. (hence showing off too many implementation details) …biting our tail here.

Comments
  • I used obj instead of this because I thought that setters and getters are actually copied. now I realized that something like Object.assign(SomeClassInstance.prototype, obj) won't work either.