美文网首页
Proxy 讲解

Proxy 讲解

作者: zhang463291046 | 来源:发表于2020-09-14 17:56 被阅读0次

    以下内容是引用或者借鉴别人的,自己只是做个笔记,方便学习。理解错误的地方,欢迎评论。如有侵权,私聊我删除,未经允许,不准作为商业用途

    Proxy 在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,可以对外界的访问进行过滤和改写。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的操作,返回一个布尔值。
    • deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
    • 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)。

    get(target, propKey, receiver)

    var target = {
      a: 'a'
    };
    
    var handler = {
      get(target, propKey, receiver){
        if (propKey in target) {
          return target[propKey];
        } else {
          throw new ReferenceError("Prop name \"" + propKey + "\" does not exist.");
        }
      }
    };
    
    var proxy = new Proxy(target, handler);
    proxy.b = 'b';
    
    console.log(proxy.a)  //a
    console.log(proxy.b)  //b
    console.log(target.c)  //undefined
    console.log(proxy.c)  //Uncaught ReferenceError: Prop name "c" does not exist.
    

    set(target, propKey, value, receiver)

    var target = {
      a: "a"
    };
    
    var handler = {
      set(target, propKey, value, receiver) {
        target[propKey] = value + 1;
        return true;  //没有返回true,就会报错
      }
    };
    
    var proxy = new Proxy(target, handler);
    proxy.b = "b";
    
    console.log(proxy.a);  //a
    console.log(proxy.b);  //b1
    

    has(target, propKey)

    var target = {
      a: "a"
    };
    
    var handler = {
      has(target, propKey) {
        return propKey in target;
      }
    };
    
    var proxy = new Proxy(target, handler);
    proxy.b = "b";
    
    console.log("a" in proxy); //true
    console.log("b" in proxy); //true
    console.log("c" in proxy);  //false
    

    deleteProperty(target, propKey)

    var target = {
      a: "a"
    };
    
    var handler = {
      deleteProperty(target, propKey) {
        if(propKey == 'b'){
          throw new Error(`Invalid attempt to delete private "${propKey}" property`);
        }
        delete target[propKey]
        return true;
      }
    };
    
    var proxy = new Proxy(target, handler);
    proxy.b = "b";
    
    delete proxy.a
    delete proxy.b  //抛出错误
    

    ownKeys(target)

    var target = {
      a: "a"
    };
    
    var handler = {
      ownKeys(target) {
        return Reflect.ownKeys(target).filter(key => key[0] !== "_");
      }
    };
    
    var proxy = new Proxy(target, handler);
    proxy._b = "b";
    
    //_b将会被拦截
    for (let key in proxy) {
      console.log(key); // a
    }
    

    getOwnPropertyDescriptor(target, propKey)

    var target = {
      a: "a"
    };
    
    var handler = {
      getOwnPropertyDescriptor(target, propKey) {
        if (propKey[0] === "_") {
          return;
        }
        return Object.getOwnPropertyDescriptor(target, propKey);
      }
    };
    
    var proxy = new Proxy(target, handler);
    proxy._b = "b";
    
    console.log(Object.getOwnPropertyDescriptor(proxy, "a"));
    // {
    //   configurable: true;
    //   enumerable: true;
    //   value: "a";
    //   writable: true;
    // }
    console.log(Object.getOwnPropertyDescriptor(proxy, "_b")); // undefined
    

    apply (target, ctx, args)

    var target = function() {};
    
    var handler = {
      apply (target, ctx, args){
        let obj = {};
        for (let key in args) {
          obj[key] = args[key];
        }
        return obj;
      }
    };
    
    var proxy = new Proxy(target, handler);
    var p = proxy('a', 'b');
    var p = proxy.call(null,'a', 'b');
    var p = proxy.apply(null,['a', 'b']);
    console.log(p);
    // {
    //   0: "a",
    //   1: "b"
    // }
    

    construct(target, args)

    var target = function() {};
    
    var handler = {
      construct(target, args) {
        let obj = {};
        for (let key in args) {
          obj[key] = args[key];
        }
        return obj;
      }
    };
    
    var proxy = new Proxy(target, handler);
    var p = new proxy('a', 'b');
    console.log(p);
    // {
    //   0: "a",
    //   1: "b"
    // }
    

    相关文章

      网友评论

          本文标题:Proxy 讲解

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