Proxy有什么优势?

1、什么是Proxy

       Proxy ES6 中原生提供的一个构造函数,Proxy 字面意思是“代理”,其实它更像一种拦截器,在访问,赋值等基本操作时会先到我们定义好的拦截方法中,根据访问的信息去执行我们想要的操作。

2、Proxy的用法

new Proxy(target, handler);

// target 参数指的是目标对象
// handler 指用户自定义的行为对象


let handler = {
    get (target, propkey, receiver) {
        console.log('getting values');
        return target[propkey] || 'value is not defined';
    },
    set (target, propkey, value, receiver) {
        console.log('setting values');
        return target[propkey] = value;
    }
}

var proxy = new Proxy({}, handler);

console.log(proxy.name);
// 输出
// getting values
// value is not defined

proxy.name = 'xiaodai';
// 输出
// setting values

console.log(proxy.name)
// 输出
// getting values
// xiaodai

        上面代码定义了一个拥有 getset 的代理,当我们在访问 proxy 对象中的 name 时,会进入 handler 中的 get 方法并执行。同样赋值给 proxy 赋值时,则会进入 hander 中的 set 方法中。

3、Proxy和defineProperty区别

        proxy 中的 get 和 set 方法和 Object.defineProperty 的 descriptorgetset 方法很像,但 proxy 中的 getset 更为强大,不仅可以监听数组下标的变化,还可以监听到对象原型属性的变化。

// proxy监听数组下标
var proxyArr = new Proxy([], {
    get(target, propkey) {
        console.log('数组下标被监听:get');
        return target[propkey];
    },
    set(target, propkey, value) {
        console.log('数组下标被监听:set');
        return target[propkey] = value;
    }
})
console.log(proxyArr[0]);
// 数组下标被监听:get
// undefined

proxyArr[0] = 'xiaodai';
// 数组下标被监听:set
// 'xiaodai'



// proxy监听对象原型
var obj = {name: 'objName'};
var prototypeObj = Object.create(obj);
var proxyPrototype = new Proxy(prototypeObj, {
    get(target, propkey) {
        console.log('对象原型被监听:get');
        return target[propkey];
    },
    set(target, propkey, value) {
        console.log('对象原型被监听:set');
        return target[propkey] = value;
    }
})
console.log(proxyPrototype.name);
// 对象原型被监听:get
// objName

proxyPrototype.name = 'xiaodai';
// 对象原型被监听:set
// xiaodai

/**
handler中的对象属性
Proxy不仅可以用于监听数据变化,还可以监听调用函数,构造函数实例化等操作
handler对象具体的参数有13个:

  get(target, propkey, receiver)
  set(target, propkey, receiver)
  has(target, propkey)
  deleteProperty(target, propkey)
  ownkeys(target)
  getOwnPropertyDescriptor(target, propKey)
  defineProperty(target, propkey, propDesc)
  preventExtensions(target)
  getPrototypeOf(target)
  isExtensible(target)
  setPrototypeOf(target, proto)
  apply(target, object, args) // 调用函数前触发
  construct(target, args) // 构造函数实例化前触发
**/

4、Proxy与defineProperty 比较 

  • defineProperty 不能监听数组下标变化和对象原型的变化,Proxy则可以支持。
  • defineProperty 监听的是一个对象的属性,proxy 监听的是整个对象。
  • defineProperty 比较 proxy 的速度更快,我们写两个测试的用例比较一下两者的速度。

// defineProperty测试用例
var defineObj = {};
console.time('defineProperty');
for (var x = 0; x < 100000; x++) {
    Object.defineProperty(defineObj, 'change_' + x, {
        get() {
            return value;
        },
        set(value) {
            return defineObj['change_' + x] = value;
        }
    });
}
console.timeEnd('defineProperty');

// defineProperty: 373.563232421875 ms



// proxy测试用例
var proxy = new Proxy({}, {
    get(target, propkey) {
        return target[propkey];
    },
    set(target, propkey, value) {
        return target[propkey] = value
    }
});
console.time('proxy');
for (var x = 0; x < 100000; x++) {
    proxy['change_' + x] = 1;
}
console.timeEnd('proxy');

// proxy: 78.904052734375 ms

        复制以上代码去 chrome 中去运行得出的时间。

5、内存比较

        那 proxydefineProperty 除了运行速度快还有其他的优势么?那是必须的。

        proxy 比 defineProperty 占用的内存更少

        运行 proxy 的测试用例

        chrome 运行 defineProperty 的测试用例 

猜你喜欢

转载自blog.csdn.net/qq_24518001/article/details/128402838