最初我的目标是设置类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中删除设置行之后),但是会有更好的实现吗? (这有点偏离主题,但我也想知道,因为我真的想删除顶层代理,它只是覆盖了构造函数)
答案 0 :(得分:1)
如果从构造函数返回一个对象,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
参数请在使用前进行实验:-)
答案 1 :(得分:0)
从MDN Proxy挖掘而来自dynamic setter/getter的灵感,
我想出了以下代码:
var OnlyOneProp = new Proxy(
// target
class{// normal class definition
constructor(){
// console.log("anonymous constructor");
}
}, {
construct(target, args, caller){
// if(!new.target){}
// console.log("proxy construct");
return new Proxy(new target(), {
set(target, name, value, receiver){
target.only_property = value;
return true; // must have according to some specification
}
});
},
});
var obj = new OnlyOneProp();
obj.what_ever_property = "value";
console.log(obj.only_property, obj.what_ever_property);
// output: value undefined
它完全正常运行但你可能会看到有两个new Proxy()
实例化(虽然第一个只执行一次),如果可能我想删除它。