Javascript代理set()继承对象的本地属性

时间:2017-01-09 07:47:19

标签: javascript inheritance proxy

根据MDNhandler.set()可以捕获Inherited属性赋值:

Object.create(proxy)[foo] = bar;

在这种情况下,如何监视并允许继承对象的本地分配?



var base = {
	foo: function(){
		return "foo";
	}
}

var proxy = new Proxy(base, {
	set: function(target, property, value, receiver){
		console.log("called: " + property + " = " + value, "on", receiver);
		//receiver[property] = value; //Infinite loop!?!?!?!?!
		//target[property] = value // This is incorrect -> it will set the property on base.
		
		/*
			Fill in code here.
		*/
		return true;
	}
})

var inherited = {}
Object.setPrototypeOf(inherited, Object.create(proxy));

inherited.bar = function(){
	return "bar";
}

//Test cases
console.log(base.foo); //function foo
console.log(base.bar); //undefined
console.log(inherited.hasOwnProperty("bar")) //true




2 个答案:

答案 0 :(得分:3)

经过一些额外的考虑,我注意到它拦截了3个操作:

  

属性赋值:proxy [foo] = bar和proxy.foo = bar   继承属性赋值:Object.create(proxy)[foo] = bar
  Reflect.set()

但不是Object.defineProperty(),它似乎比=运算符更低。

因此以下工作:



var base = {
    foo: function(){
        return "foo";
    }
};

var proxy = new Proxy(base, {
    set: function(target, property, value, receiver){
        var p = Object.getPrototypeOf(receiver);
      
        Object.defineProperty(receiver, property, { value: value });   // ***
        return true;
    }
});

var inherited = {};
Object.setPrototypeOf(inherited, Object.create(proxy));

inherited.bar = function(){
    return "bar";
};

// Test cases
console.log(base.foo);                       // function foo
console.log(base.bar);                       // undefined
console.log(inherited.bar);                  // function bar
console.log(inherited.hasOwnProperty("bar")) // true




答案 1 :(得分:1)

我看到两个选项(可能):

  1. 将属性存储在Map中,使接收方键入的Map中的各种接收器的WeakMap保持不变。通过检查get并在那里返回映射而不是从对象返回来满足Map。 (还有has。)轻微的问题是你还需要代理接收器(而不仅仅是base)才能处理ownKeys。所以这可能是行不通的。

  2. 设置时暂时将代理从继承链中取出。

  3. 这是第二个:

    
    
    var base = {
        foo: function(){
            return "foo";
        }
    };
    
    var proxy = new Proxy(base, {
        set: function(target, property, value, receiver){
            const p = Object.getPrototypeOf(receiver); // ***
            Object.setPrototypeOf(receiver, null);     // ***
            receiver[property] = value;                // ***
            Object.setPrototypeOf(receiver, p);        // ***
            return true;
        }
    });
    
    var inherited = {};
    Object.setPrototypeOf(inherited, Object.create(proxy));
    
    inherited.bar = function(){
        return "bar";
    };
    
    // Test cases
    console.log("base.foo:", base.foo); // function foo
    console.log("base.bar:", base.bar); // undefined
    console.log("inherited.bar:", inherited.bar); // function bar
    console.log("inherited has own bar?", inherited.hasOwnProperty("bar")); // true