为什么使用扩展语法复制对象后 getter/setter 不再起作用?

jer*_*Tob 2 javascript object spread-syntax

在下面的代码片段中,扩展语法的工作方式我不太理解:

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
Run Code Online (Sandbox Code Playgroud)

您能否解释一下为什么在这种情况下重新分配名称不起作用?

Cer*_*nce 5

扩展对象不会复制 getter 和 setter 方法 - 相反,扩展操作仅获取属性(即,它调用getter,如果有的话),并将结果分配给结果对象(此处的spread_obj),只需就像普通对象一样,没有任何 getter 或 setter。如果将日志语句放入 setter 和 getter 中,您可以看到这一点。结果spread_obj有一个setName属性,undefined因为它setName只是一个 setter 方法,不返回任何内容。

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
Run Code Online (Sandbox Code Playgroud)

另请注意,如果您想使用代码的第二部分,您可能应该将 setter 和 getter 方法更改为引用this而不是 to obj,否则结果可能不直观;您的 getter 和 setter 方法区域始终引用.name上的属性obj,而不是.name标准调用上下文上的属性(即 tospread_obj或 to create_obj)。当您尝试分配给 时spread_obj.setName,您实际上更改了原始 obj.name属性:

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

let create_obj1 = Object.create(obj)
create_obj1.setName = 'Marion Luke1'

let create_obj2 = Object.create(obj)
create_obj2.setName = 'Marion Luke2'
// "Marion Luke2", but we're logging the property from the "first" object!
console.log('create_obj name', create_obj1.name)
Run Code Online (Sandbox Code Playgroud)

通过参考this而不是修复obj

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

let create_obj1 = Object.create(obj)
create_obj1.setName = 'Marion Luke1'

let create_obj2 = Object.create(obj)
create_obj2.setName = 'Marion Luke2'
console.log(create_obj1.name)
Run Code Online (Sandbox Code Playgroud)