为什么 getter/setter 在使用传播语法复制对象后不再起作用?
Why are getter/setter no longer working after copying an object with the 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
你能解释一下为什么在这种情况下名称的重新分配不起作用吗?
传播对象不会复制 getter 和 setter 方法 - 相反,传播操作仅 gets 属性(即,它 调用 getter,如果有的话),并将结果赋值给结果对象(这里是 spread_obj
),就像普通对象一样,没有任何 getters 或 setters。如果将日志语句放在 setter 和 getter 中,就可以看到这一点。结果 spread_obj
有一个 undefined
的 setName
属性 因为 setName
只是一个 setter 方法,而不是 return任何东西。
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
另请注意,如果您想使用代码的第二部分,您可能应该更改 setter 和 getter 方法以引用 this
而不是 obj
,否则结果可能不直观;您的 getter 和 setter 方法区域总是引用 obj
上的 .name
属性,而不是 .name
属性标准调用上下文(即 spread_obj
或 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)
参考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)
除了@CertainPerformances 的解释之外,我还要补充一点,当使用 getters/setters 时,这种行为似乎更明智,更传统的做法是为 get 和 set 指定一个名称。
例如,当您的对象看起来像这样时,一切都会好一些(至少在表面上):
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)
看起来工作量很大,但由于对象传播只需要可枚举的属性,您可以使 _name
不可枚举。那么一切都显得理智一点:
let obj = {
set name(name){
this._name = name
},
get name() {
return this._name
}
}
Object.defineProperty(obj, '_name', {
enumerable: false,
writable: true,
configurable: true
});
obj.name = 'Jon Doe'
let spread_obj = {...obj}
spread_obj.name = 'Marion Luke'
// now spread_obj only has a name prop:
console.log(spread_obj)
// and obj too:
console.log(obj)
select答案是错误的。
- getter/setter不是方法,是特殊属性。
- ...spread 和 object.assign 将不起作用,只是因为它们将 getter/setter 视为普通可枚举 属性,它们
复制它的 'value',所以 getter/setter 会失败。
如果要复制,可以参考undercore.js扩展方法:
这是我的分配代码:
const assign = (ob, ...o) => {
o.forEach(obj=>{if (typeof obj !== 'undefined')
Object.defineProperties(ob, Object.getOwnPropertyDescriptors(obj));})
return ob;
};
在下面的代码片段中,传播语法的工作方式我不太理解:
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
你能解释一下为什么在这种情况下名称的重新分配不起作用吗?
传播对象不会复制 getter 和 setter 方法 - 相反,传播操作仅 gets 属性(即,它 调用 getter,如果有的话),并将结果赋值给结果对象(这里是 spread_obj
),就像普通对象一样,没有任何 getters 或 setters。如果将日志语句放在 setter 和 getter 中,就可以看到这一点。结果 spread_obj
有一个 undefined
的 setName
属性 因为 setName
只是一个 setter 方法,而不是 return任何东西。
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
另请注意,如果您想使用代码的第二部分,您可能应该更改 setter 和 getter 方法以引用 this
而不是 obj
,否则结果可能不直观;您的 getter 和 setter 方法区域总是引用 obj
上的 .name
属性,而不是 .name
属性标准调用上下文(即 spread_obj
或 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)
参考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)
除了@CertainPerformances 的解释之外,我还要补充一点,当使用 getters/setters 时,这种行为似乎更明智,更传统的做法是为 get 和 set 指定一个名称。
例如,当您的对象看起来像这样时,一切都会好一些(至少在表面上):
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)
看起来工作量很大,但由于对象传播只需要可枚举的属性,您可以使 _name
不可枚举。那么一切都显得理智一点:
let obj = {
set name(name){
this._name = name
},
get name() {
return this._name
}
}
Object.defineProperty(obj, '_name', {
enumerable: false,
writable: true,
configurable: true
});
obj.name = 'Jon Doe'
let spread_obj = {...obj}
spread_obj.name = 'Marion Luke'
// now spread_obj only has a name prop:
console.log(spread_obj)
// and obj too:
console.log(obj)
select答案是错误的。
- getter/setter不是方法,是特殊属性。
- ...spread 和 object.assign 将不起作用,只是因为它们将 getter/setter 视为普通可枚举 属性,它们 复制它的 'value',所以 getter/setter 会失败。
如果要复制,可以参考undercore.js扩展方法:
这是我的分配代码:
const assign = (ob, ...o) => {
o.forEach(obj=>{if (typeof obj !== 'undefined')
Object.defineProperties(ob, Object.getOwnPropertyDescriptors(obj));})
return ob;
};