ES6中的代理模式——Proxy

什么是Proxy对象

Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。

Proxy用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和改写。这个词的原理为代理,在这里可以表示由它来“代理”某些操作,译为“代理器”。

简单来说: Proxy 对象就是可以让你去对JavaScript中的一切合法对象的基本操作进行自定义。然后用你自定义的操作去覆盖其对象的基本操作。也就是当一个对象去执行一个基本操作时,其执行的过程和结果是你自定义的,而不是对象的。

Proxy的语法:
let p = new Proxy(target, handler);

Proxy对象的所有用法,都是上面的这种形式。不同的只是handle参数的写法。
其中:new Proxy用来生成Proxy实例,
target是表示所要拦截的对象,是你要代理的对象。它可以是JavaScript中的任何合法对象。如: (数组, 对象, 函数等等)
handle是用来定制拦截行为的对象(自定义操作方法的一个集合)。
p 是一个被代理后的新对象,它拥有 target 的一切属性和方法。只不过其行为和结果是在 handler 中自定义的。

var obj = new Proxy({}, {
  get: function (target, propKey, receiver) {
    console.log(`getting ${propKey}!`);
    return Reflect.get(target, propKey, receiver);
  },
  set: function (target, propKey, value, receiver) {
    console.log(`setting ${propKey}!`);
    return Reflect.set(target, propKey, value, receiver);
  }
});

举个栗子:

    let obj={
        a:10,
        b:20,
    }
    const p=new Proxy(obj,{
        get(target,key,value){
            if(key ==='c'){
                return '我是自定义的结果'
            }else{
                return target[key];
            }
        },
        set(target,key,value){
            if(value===4){
                target[key]='我是自定义的结果';
            }else{
                target[key]=value;
            }
        }
    })

    console.log(obj.a) // 10
    console.log(obj.c) // undefined
    console.log(p.a) // 10
    console.log(p.c) // 我是自定义的结果
    
    obj.name = '李白';
    console.log(obj.name); // 李白
    obj.age = 4;
    console.log(obj.age); // 4
    p.name = '李白';
    console.log(p.name); // 李白
    p.age = 4;
    console.log(p.age); // 我是自定义的结果

以上,构造一个代理对象时所传的第二个参数 handler,这个handler对象是有get、set两个函数方法组成的。
没代理的对象所得的结果是其JavaScript本身的执行机制运行计算后所得到的,而被代理了的对象的结果则是我们自定义的。
实际上 handler 本身就是ES6所新设计的一个对象,它的作用就是用来自定义代理对象的各种可代理操作。
下面是 Proxy 支持的拦截操作一览,一共 13 种:

  • get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。
  • set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
  • has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
    // 在判断代理对象是否拥有某个属性时触发该操作,比如在执行 "foo" in proxy 时。
  • deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
    // 在删除代理对象的某个属性时触发该操作,比如在执行 delete proxy.foo 时。
  • ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
  • getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
  • defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
  • preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。
  • getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。
  • isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。
  • setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
  • apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
  • construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
Proxy的作用

对于代理模式 Proxy 的作用主要体现在三个方面:
1、 拦截和监视外部对对象的访问
2、 降低函数或类的复杂度
2、 在复杂操作前对操作进行校验或对所需资源进行管理

你可能感兴趣的:(ES6中的代理模式——Proxy)