最初,我的目标是设置类OnlyOneProp
的实例的任何属性,
即obj.what_ever_property = "value"
,
最后只会修改obj.the_only_prop
。
行为是这样的:
var obj = new OnlyOneProp();
obj.what_ever_property = "value";
console.log(obj.only_property, obj.what_ever_property);
// expected output:
// >value undefined
原始问题:有没有办法实现上述行为?
编辑:
关于solution in the answer,
以下是一些后续问题:
1)以上代码是否有重大缺陷? (就像我曾经混淆了
receiver
和target
一样,这可能会在设置器上造成无限循环)2)
Proxy
是否会严重阻碍性能?3)有什么方法可以绕过上述代理设置器? (就像
defineProperty()
一样)4)也可以是ReadOnlyObject的实现(在setter中删除设置行之后),但是会有更好的实现吗? (这有点不合时宜,但我也想知道,因为我真的想删除仅覆盖构造函数的顶级Proxy)
最佳答案
如果从构造函数返回对象,则new
运算符将返回该对象,而不是作为this
传递给构造函数的新对象。所以OnePropertyClass
的更直接的版本可能是
class OnePropertyClass{
constructor( value) {
var self = this;
return new Proxy( this, {
set: function(target, property, value) {
self["only_property"] = value;
return true;
}
}
);
}
}
这可以通过使用箭头函数而不是闭包来简化:
class OnePropertyClass{
constructor() {
return new Proxy( this, {
set: (target, property, value) => {
this.only_property = value;
return true;
}
}
);
}
}
var obj = new OnePropertyClass();
obj.what_ever_property = "value";
console.log(obj.only_property, obj.what_ever_property);
它不会设置任何setter循环,因为setter将值存储在构造函数的实际
this
对象上,而不是存储在返回的代理对象上。此版本的
OnePropertyClass
实例通常照常继承-constructor
属性返回OnePropertyClass
构造函数,而Object.prototype
属性和方法仍被继承。您可能希望冻结
OnePropertyClass.prototype
以防止添加任何其他继承的属性。您可能还希望为defineProperty
以及可能为setPrototype
提供陷阱功能,以防止添加运行时属性-有关详细信息,请参见MDN handler object methods。代理的实现可能是用C ++编写的,我希望大多数额外的开销将在于调用setter函数。
我尚未测试此版本的可扩展性,并且未使用
target
处理程序的set
参数请在使用前进行实验:-)