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.其他方法
has(target,propkey)
- 拦截
hasProperty()
、propkey in proxy
操作,返回一个布尔值;deleteProperty(target,propkey)
- 拦截
delete proxy[propkey]
操作,返回一个布尔值;ownKeys(target)
- 拦截
Object.getOwnPropertyNarnes(proxy)
、Object.getOwnPropertySyrnbols (proxy)
、Object.keys(proxy)
,返回一个数组。该方法返回目标对象所有自身属性的属 性名,而 Object .keys()的返回结果仅包括目标对象自身的可遍历属性;getOwnPropertyDescriptor(target,propkey)
- 拦截
Object.getOwnPropertyDescriptor(proxy, propKey)
,返回属性的描述对象;defineProperty(target,propkey)
- 拦截
Object.defineProperty(proxy, propKey, propDesc)
、Object.define Properties(proxy, propDescs)
,返回一个布尔值;preventExtensions(target)
- 拦截
Object . preventExtensions (proxy)
,返回一个布尔值;getPrototypeOf(target)
- 拦截
Object.getPrototypeOf(proxy)
,返回一个对象;isExtensible(target)
- 拦截
Object.isExtensible(proxy)
,返回一个布尔值;setPrototypeOf(target)
- 拦截
Object.setPrototypeOf(proxy,proto)
,返回一个布尔值;若对象为函数,则还有二外两种操作可以拦截(apply,construct)construct(target,args)
- 拦截Proxy实例作为构造函数调用的操作,比如 new proxy(…args);
本文地址:https://blog.csdn.net/yivisir/article/details/107895266