欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ES6:关于Proxy,你知道多少?

程序员文章站 2022-06-24 11:20:42
ES6:关于Proxy,你知道多少?概述Proxy用于修改某些操作的默认行为,等同于在语言层面上做出修改,所以属于一种“元编程”,即对编程语言进行编程。Proxy可以理解成在目标对象前架设一层拦截层,外界访问该对象都必须先通过这层拦截,因此提供一种机制可以对外界的访问进行拦截或过滤。实例的方法1.get()get方法用于拦截某个属性的读取操作。let person = { name : '张三'}let proxy = new Proxy(person,{ get...

ES6:关于Proxy,你知道多少?

概述

  • Proxy用于修改某些操作的默认行为,等同于在语言层面上做出修改,所以属于一种“元编程”,即对编程语言进行编程。
  • Proxy可以理解成在目标对象前架设一层拦截层,外界访问该对象都必须先通过这层拦截,因此提供一种机制可以对外界的访问进行拦截或过滤。

实例的方法

1.get()

  • get方法用于拦截某个属性的读取操作。
let person = {
    name : '张三'
}

let proxy = new Proxy(person,{
    get : function(target,property){
        if(property in target){
            return target[property];
        }else{
            throw new Error('property ' + property + ' no found!')
        }
    }
})

proxy.name;		//'张三'
proxy.age;		//property age no found!

以上的实例当获取对象没有的属性age时,就会抛出错误;若不通过代理,则会返回undefined;

  • get方法可以继承
let proto = new Proxy({},{
    get(target,propertykey,receiver){
        console.log('get '+ propertykey);
        return target[propertykey];
    }
});

let obj = Object.create(proto);
obj.lalala; 		//get lalala
  • 利用Proxy对象,可以将读取属性的操作变为执行某个函数,从而实现函数的链式操作;
let pipe = (function(){
    return function(value){
        //创建函数执行栈
        let funcStack = [];
        //创建拦截器
        let oproxy = new Proxy({},{
            get: function(pipeObj,fnName){
                //当属性为get,返回函数栈一次执行函数后的结果
                if(fnName === 'get'){
                    return funcStack.reduce(function(val,fn){
                        return fn(val);
                    },value)
                }
                //否则将函数置入函数执行栈中,并返回又一个拦截器
                else{
                    funcStack.push(window[fnName]);
                    return oproxy;
                }
            }
        });
       // 将拦截器返回给pipe 
        return oproxy;
    }
}())

let double = n=>n*2;
let pow = n=>n*n;

pipe(2).double.pow.get;		//16

2.set()

  • set方法用户拦截某个属性的赋值操作
let ageLimit = {
    set : function(obj,prop,val){
        if(prop === 'age'){
            if(!Number.isInteger(val)){
                throw new TypeError('the age must be a integer')
            }
            if(val > 150 || val < 0){
                throw new RangeError('the age must be from 0 to 150')
            }
        }
        
        obj[prop] = val;
    }
}

let person = new Proxy({},ageLimit);
person.age = 200;	//the age must be from 0 to 150;
person.age = 'abc'	//the age must be a integer;
person.age = 20;	//正常
person.age;			// 20;
  • 通过ageLimit拦截器,可以及时对用户的数据输入做数据验证,以保证数值规范;
  • 有时候,我们会在对象上设置内部属性,属性名的第一个字符为下划线’_’,表示该属性不能被外部访问或使用。结合get和set方法,就可以做到防止内部属性被外部读写;
let handler = {
    get (target , key){
        invariant(key,'get');
        return target[key];
    },
    set (target , key , value){
        invatiant(key,'set');
        taget[key] = value;
        return true;
    }
}


function invariant(key,action){
    if(key[0] === '_'){
        throw new Error('no allowed to ' + action + ' the property');
    }
}

let target = {
    _name : '张三',
    _age : 20
};
let proxy = new Proxy(target,handler);
proxy._name;	// no allowed to get the property
proxy._age = 12	// no allowed to set the property

3.apply()

  • apply方法拦截函数的调用、call、apply操作
  • apply方法接收三个参数:目标对象、目标对象的上下文的this、目标对象的参数数组
let target = function(){
    console.log('I am the target');
}

let handler = {
    apply : function(){
        console.log('I am the apply');
    }
}

let p = new Proxy(target,handler);

p();	//I am the apply;

4.其他方法

  1. has(target,propkey)

    • 拦截hasProperty()propkey in proxy操作,返回一个布尔值;
  2. deleteProperty(target,propkey)

    • 拦截delete proxy[propkey]操作,返回一个布尔值;
  3. ownKeys(target)

    • 拦截Object.getOwnPropertyNarnes(proxy)Object.getOwnPropertySyrnbols (proxy)Object.keys(proxy),返回一个数组。该方法返回目标对象所有自身属性的属 性名,而 Object .keys()的返回结果仅包括目标对象自身的可遍历属性;
  4. getOwnPropertyDescriptor(target,propkey)

    • 拦截 Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象;
  5. defineProperty(target,propkey)

    • 拦截 Object.defineProperty(proxy, propKey, propDesc)Object.define Properties(proxy, propDescs),返回一个布尔值;
  6. preventExtensions(target)

    • 拦截 Object . preventExtensions (proxy) ,返回一个布尔值;
  7. getPrototypeOf(target)

    • 拦截Object.getPrototypeOf(proxy),返回一个对象;
  8. isExtensible(target)

    • 拦截Object.isExtensible(proxy),返回一个布尔值;
  9. setPrototypeOf(target)

    • 拦截Object.setPrototypeOf(proxy,proto),返回一个布尔值;若对象为函数,则还有二外两种操作可以拦截(apply,construct)
  10. construct(target,args)

    • 拦截Proxy实例作为构造函数调用的操作,比如 new proxy(…args);

本文地址:https://blog.csdn.net/yivisir/article/details/107895266