ES6 proxy(2)

proxy 概述

proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种"元编程",即对编程语言进行编程。

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

es6提供proxy构造函数,用于生成proxy实例

proxy对象的所有用法都是上面这种形式,不同的只是handler参数的写法,其中new Peoxy()表示生成一个proxy实例,target参数表示要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。
  • proxy实例方法 -->defineProperty()
    defineProperty()拦截Object.defineProperty操作
 {
            var handler = {
                defineProperty(target, key , descriptor){
                    return false;
                }
            };
            var target = {foo:'123'};

            var proxy = new Proxy(target,handler);
            console.log(Object.defineProperty(proxy,'foo',{
                writable:false
            }));
            // 'defineProperty' on proxy: trap returned falsish for property 'foo'
        }
  • proxy实例方法 -->getOwnPropertyDescriptor()
    getOwnPropertyDescriptor()拦截Object.getOwnPropertyDescriptor(),返回一个属性描述对象或者undefined。
  {
            let handler = {
                getOwnPropertyDescriptor(target, key){
                    if(key[0] === '_'){
                        return;
                    }
                    return Object.getOwnPropertyDescriptor(target,key);
                }
            }
            let target = {_foo:'bar',baz:'tar'};
            let proxy = new Proxy(target,handler);
            console.log(Object.getOwnPropertyDescriptor(proxy,'low'));
            //false
            console.log(Object.getOwnPropertyDescriptor(proxy,'baz'));
            //{value: "tar", writable: true, enumerable: true, configurable: true}
            console.log(Object.getOwnPropertyDescriptor(proxy,'_foo'));
            //false
        }
    该方法对内置属性或者以下划线开头的属性返回undefined
  • proxy实例方法 -->getPrototypeOf()
    getPrototypeOf()方法主要用来拦截获取对象原型。

     主要用来拦截以下方法
     + Object.prototype.__proto__
     + Object.prototype.isPrototypeOf
     + Object.getPrototypeOf()
     + Reflect.getPrototypeOf()
     + instanceof
    
 {
            //举个例子
            let proto  = {};
            let p = new Proxy({},{
                getPrototypeOf(target){
                    return proto;
                }
            })

            console.log(Object.getPrototypeOf(p) === proto);
            //true
            //上面的代码,getPrototypeOf方法拦截了Object.getPrototypeOf(),返回了proto对象。
        }
  • proxy实例方法 -->isExtensible()
    isExtensible()方法拦截Object.isExtensible操作
  {
            let p = new Proxy({},{
                isExtensible(target){
                    console.log("called");
                    return true;
                }
            })

            console.log(Object.isExtensible(p));

            // called
            // true
        }
  • proxy实例方法 -->ownKeys()
    ownkeys方法用来拦截对象自身属性的读取操作

     + Object.getOwnPropertyNames()
     + Object.getOwnPropertySymbols()
     + Object.keys()
    
  {
            //举个例子
            let target = {
                a:1,
                b:2,
                c:3
            };
            console.log(Object.keys(target));
            //(3) ["a", "b", "c"]

            let handler = {
                ownKeys(target){
                    return ['a'];
                }
            }

            let proxy = new Proxy(target, handler);

            console.log(Object.keys(proxy));
            //['a']
        }

  • proxy实例方法 --> Proxy.revocable()
    Proxy.revocable() 方法返回一个可取消的Proxy实例
  {
            let target = {};
            let handler = {};

            let {proxy, revoke} = Proxy.revocable(target, handler);

            console.log(proxy.foo = 300);
            //300

            revoke()
            
            console.log(proxy.foo = 123);
            // Cannot perform 'set' on a proxy that has been revoked
        }

proxy.revocable 的一个使用场景是,目标对象不允许直接访问,唏嘘通过代理访问,一旦访问结束, 就要收回代理权,不允许再次访问

  • proxy实例方法 -->setPrototypeOf()
    setPrototypeOf方法主要用于拦截Object.setPrototypeOf
  {
            let handler = {
                setPrototypeOf(target, proto) {
                    throw new Error('Changing the prototype is forbidden');
                }
            }
            let proto = {};
            let target = function () {};
            let proxy = new Proxy(target, handler);

            console.log(Object.setPrototypeOf(proxy, proto));
            //Changing the prototype is forbidden 
        }

  • proxy --> this问题
    虽然proxy可以代理目标对象的访问,但是他不是目标对象的透明代理,即目标对象this关键字会指向proxy
 {
            let target = {
                m(){
                    console.log(this === proxy);
                }
            }

            let handler = {};
            let proxy = new Proxy(target, handler);

            console.log(target.m());  //false
            console.log(proxy.m());     //true
        }
发布了85 篇原创文章 · 获赞 16 · 访问量 6111

猜你喜欢

转载自blog.csdn.net/qq_43955202/article/details/104283755