你不知道的Reflect.set,Proxy.set与Proxy.defineProperty

397 阅读1分钟

前言

最近在复习阮老师《ECMAScript6入门》,回顾以前学习的知识点,这已经是我第N遍看这本书了,每次看都能有不同的感受。今天在看Reflect.set api的时候,有这样一句话。 我在想为什么有这样一种行为? 对ES6有一定了解的朋友应该知道,在对一个对象使用Proxy时,如果需要默认行为,就离不开Reflect,像这样: 上面的例子说明一个问题,当要对"对象设置属性"这种行为使用Proxy,则需要使用Reflect.set这个api,像这样: 但是上文说到了,当给Reflect.set方法传入了receiver了,则会执行Proxy.defineProperty方法; 请见下面的分析过程。

分析

如果Reflect.set没有传入receiver,则会直接将Proxy中target对象修改键值对; 而传入receiver,则会将"修改"行为设置receiver对象上(receiver一般情况下为proxy对象),修改一个对象的属性底层调用的是Object.defineProperty方法,所以会触发proxy对象的definePropery行为,请见下面示例代码:

const target = {foo: 1};
const handler = {
    set(target, key, value, receiver) {
        console.log('进入handler的set方法...');
        console.log('---enter---');
        Reflect.set(...arguments);
        console.log('---exit---');
    },
    defineProperty(target, key, desc) {
        console.log('进入handler的defineProperty方法...');
        console.log('值还未修改: ', Reflect.get(target, key));
        Reflect.defineProperty(...arguments);
        console.log('值已经修改: ', Reflect.get(target, key));
    }
};
const p = new Proxy(target, handler);
p.foo = 2;

输出结果: