DEV Community

Discussion on: The tale of three dots in Javascript

 
adam_cyclones profile image
Adam Crockett 🌀

As soon as I wake up tomorrow, I'm gonna check this out in some console, I ask because 'assign' doesn't copy getters and setters, having used that for years and years, it came as a bit of a shock.

Thread Thread
 
worsnupd profile image
Daniel Worsnup

I, too, was curious about this, so I decided to run some code in the console! It looks like both spread and assign will copy "normal" getters, but they will not copy getters that are explicitly marked as non-enumerable using Object.defineProperty or Reflect.defineProperty:

const obj1 = {
  get test() { return 'test' }
}

const obj2 = {}
Reflect.defineProperty(obj2, 'test', {
  enumerable: false,
  get() { return 'test' }
})

console.log(Object.keys(obj1)) // ['test']
console.log(Object.keys(obj2)) // []

const obj1Spread = { ...obj1 }
const obj1Assign = Object.assign({}, obj1)

const obj2Spread = { ...obj2 }
const obj2Assign = Object.assign({}, obj2)

console.log(Object.keys(obj1Spread)) // ['test']
console.log(Object.keys(obj1Assign)) // ['test']
console.log(Object.keys(obj2Spread)) // []
console.log(Object.keys(obj2Assign)) // []

However, when an object is an instance of a class that defines a getter, the getter is on the object's prototype and so it doesn't show up during enumeration and therefore doesn't get copied with object spread/assign:

class MyClass {
  get test() { return 'test' }
}

const obj = new MyClass()
const objSpread = { ...obj }

console.log(Object.keys(obj), Object.keys(objSpread)) // [], []

I would assume this behavior to be consistent with setters.