在构造函数中使用Object.assign设置getter和setter

14

我尝试通过Object.assign在构造函数中定义getter和setter:

function Class() {
  Object.assign(this, {
    get prop() { console.log('call get') },
    set prop(v) { console.log('call set') },
  });
}

var c = new Class(); // (1) => 'call get'
console.log(c.prop); // (2) => undefined
c.prop = 'change';
console.log(c.prop); // (3) => 'change' 

问题:

(1) 为什么会调用 getter?

(2) 为什么没有调用 getter?

(3) 为什么 setter 被忽略了?

1个回答

22

你的三个问题的答案都是相同的: Object.assign 读取源对象中属性的,而不会复制getters/setters。

如果查看属性描述符,您可以看到这一点:

var source = {
  get prop() { },
  set prop(v) { }
};
console.log("descriptor on source", Object.getOwnPropertyDescriptor(source, "prop"));
var target = Object.assign({}, source);
console.log("descriptor on target", Object.getOwnPropertyDescriptor(target, "prop"));

要在Class内部定义this的属性,使用defineProperty

function Class() {
  Object.defineProperty(this, "prop", {
    get() { console.log('call get') },
    set(v) { console.log('call set') },
  });
}
var c = new Class();
console.log(c.prop); // => 'call get', undefined
c.prop = 'change'; // => 'call set'
console.log(c.prop); // => 'call get', undefined


将它们反转可以起作用 return Object.assign({ get prop() { console.log('调用get') }, set prop(v) { console.log('调用set') }}, this); } - wmik
1
@wmik - 不完全是这样:如果你这样做,结果对象将不是该类的实例,而是你作为第一个参数传递给Object.assign的原始对象。 - T.J. Crowder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接