美文网首页ES6
ES6中的代理模式——Proxy

ES6中的代理模式——Proxy

作者: 我写的代码绝对没有问题 | 来源:发表于2019-12-23 16:13 被阅读0次

    什么是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

        本文链接:https://www.haomeiwen.com/subject/chjznctx.html