Javascript类泛型setter的实现(在不知道属性名的情况下修改setter)

时间:2018-01-25 06:20:13

标签: javascript class generics

最初我的目标是设置类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)上述代码是否有任何重大缺陷? (就像我曾经混淆了receivertarget,这可能会导致设置器无限循环)

2)Proxy会阻碍表现吗?

3)有没有办法绕过上面的代理设置器? (比如defineProperty()左右)

4)它也可以是ReadOnlyObject的一个实现(在setter中删除设置行之后),但是会有更好的实现吗? (这有点偏离主题,但我也想知道,因为我真的想删除顶层代理,它只是覆盖了构造函数)

2 个答案:

答案 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以防止添加任何其他继承的属性。您可能还希望为definePropertysetPrototype提供陷阱功能以防止添加运行时属性 - 有关详细信息,请参阅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()实例化(虽然第一个只执行一次),如果可能我想删除它。