Proxy:代理器,改变对象的默认访问行为;在对象的访问行为之前增设拦截,通过Proxy实例进行的访问行为都必须经过设置的拦截;在拦截中可以根据需要 设置拦截条件
p()为自定义函数,后文中的p()都是调用这个函数
????????let p = function(){ ?? ??? ??? ?console.log(...arguments); ?? ??? ?}
目录
拦截器
一、数组代理
二、对象代理
三、函数代理
四、class代理
五、ES5中的代理
拦截器
拦截器 | 作用 | get | 拦截对象属性的读取,如obj.key,obj['key'],返回属性值 | set | 拦截属性的设置,返回布尔值 | has | 拦截key in obj的操作,返回布尔值 | ownKeys | 拦截遍历如: ????????for in 循环 ?? ??? ?Object.getOwnPropertyNames(obj); ?? ??? ?Object.getOwnPropertySymbols(obj); ?? ??? ?Object.keys(obj); |
一、数组代理
1、拦截获取值的操作
2、拦截设置操作,给数组赋值或者添加元素时触发如:arr.push(xxx),arr[0] = xxx
let arr = [1,2,3,4,5];
arr = new Proxy(arr,{
? ? ? ? //如果元素存在返回值,否则返回error
? ? ? ? get(target,prop){//target为代理的对象,此处为数组arr;prop此处为索引
? ? ? ? ? ? ? ? return prop in target ? target[prop] : 'error';
????????},
? ? ? ? //设置值时触发
? ? ? ? set(target,prop,val){
? ? ? ? ? ? ? ? if(typeof val === 'number'){//是数值类型添加,否则报错,
? ? ? ? ? ? ? ? ? ? ? ?target[prop] = val;//可根据实际需要修改条件
????????????????????????return true;
????????????????}else return false;
????????}
})
二、对象代理
1、拦截是否存在如in
????????let age = { ?? ??? ??? ?min:0, ?? ??? ??? ?max:143 ?? ??? ?} ?? ??? ?age = new Proxy(age,{ ?? ??? ??? ?has(target,prop){ ?? ??? ??? ??? ?return prop >= target.min && prop <= target.max; ?? ??? ??? ?} ?? ??? ?}) ?? ??? ?p(23 in age); ?? ??? ?p(144 in age);
2、拦截遍历如:
????????for in 循环 ?? ??? ?Object.getOwnPropertyNames(obj); ?? ??? ?Object.getOwnPropertySymbols(obj); ?? ??? ?Object.keys(obj);
????????let user = { ?? ??? ??? ?name:"Asia", ?? ??? ??? ?age:23, ?? ??? ??? ?_password:'666' ?? ??? ?} ?? ??? ?user = new Proxy(user,{ ?? ??? ??? ?ownKeys(target){
? ? ? ? ? ? ? ? //将对象的所有键中以'_'开头的键过滤掉,此处过滤了密码属性 ?? ??? ??? ??? ?return Object.keys(target).filter(key => !key.startsWith('_'));//可根据需要自定义拦截条件 ?? ??? ??? ?} ?? ??? ?}); ?? ??? ?for(let key in user){ ?? ??? ??? ?p(key); ?? ??? ?}
3、拦截某些属性一切操作
????????let u = { ?? ??? ??? ?name:'Asia', ?? ??? ??? ?age:23, ?? ??? ??? ?_password:'666' ?? ??? ?} ?? ??? ?u = new Proxy(u,{ ?? ??? ??? ?set(obj,key,val){ ?? ??? ??? ??? ?if(key.startsWith('_')){ ?? ??? ??? ??? ??? ?throw new Error('不可修改'); ?? ??? ??? ??? ?}else{ ?? ??? ??? ??? ??? ?obj[key] = val; ?? ??? ??? ??? ?} ?? ??? ??? ?}, ?? ??? ??? ?get(obj,key){ ?? ??? ??? ??? ?if(key.startsWith('_')){ ?? ??? ??? ??? ??? ?throw new Error('不可访问'); ?? ??? ??? ??? ?}else{ ?? ??? ??? ??? ??? ?return obj[key]; ?? ??? ??? ??? ?} ?? ??? ??? ?}, ?? ??? ??? ?deleteProperty(obj,key){ ?? ??? ??? ??? ?if(key.startsWith('_')){ ?? ??? ??? ??? ??? ?throw new Error('不可删除'); ?? ??? ??? ??? ?}else{ ?? ??? ??? ??? ??? ?delete obj[key]; ?? ??? ??? ??? ??? ?return true; ?? ??? ??? ??? ?} ?? ??? ??? ?}, ?? ??? ??? ?ownKeys(obj,key){ ?? ??? ??? ??? ?return Object.keys(obj).filter(key => !key.startsWith('_')); ?? ??? ??? ?} ?? ??? ?}) ?? ??? ? ?? ??? ?try{ ?? ??? ??? ?u._password = '000'; ?? ??? ?}catch(err){ ?? ??? ??? ?p(err.message); ?? ??? ?}; ?? ??? ? ?? ??? ?try{ ?? ??? ??? ?p(u._password); ?? ??? ?}catch(err){ ?? ??? ??? ?p(err.message); ?? ??? ?} ?? ??? ? ?? ??? ?try{ ?? ??? ??? ?delete u._password; ?? ??? ??? ? ?? ??? ?}catch(err){ ?? ??? ??? ?p(err.message); ?? ??? ?} ?? ??? ?Object.keys(u).forEach(key => p(u[key]));?
三、函数代理
改变函数返回值
????????let sum = (...args) => { ?? ??? ??? ?let sum = 0; ?? ??? ??? ?args.forEach(item => { ?? ??? ??? ??? ?sum += item; ?? ??? ??? ?}); ?? ??? ??? ?return sum; ?? ??? ?} ?? ??? ?sum = new Proxy(sum,{ ?? ??? ??? ?apply(fn,ctx,args){ ?? ??? ??? ??? ?return fn(...args) * 10; ?? ??? ??? ?} ?? ??? ?}); ?? ??? ?p(sum(1,2,3));//60 ?? ??? ?p(sum.call(null,1,2,3));//60 ?? ??? ?p(sum.apply(null,[1,2,3]));//60
四、class代理
对new进行拦截
let User = class{ ?? ??? ??? ?constructor(name){ ?? ??? ??? ??? ?this.name = name; ?? ??? ??? ?} ?? ??? ?} ?? ??? ?User = new Proxy(User,{ ?? ??? ??? ?construct(cls,args,newCls){ ?? ??? ??? ??? ?p('construct 正在拦截'); ?? ??? ??? ??? ?return new cls(...args); ?? ??? ??? ?} ?? ??? ?}); ?? ??? ?p(new User('Asia'));
五、ES5中的代理
Object.definePrototype(obj,属性名,callback);
let obj = {};
let _name = '';
Object.definePrototype(obj,'name',{
? ? ? ? set(val){
? ? ? ? ? ? ? ? _name = val;
????????},
? ? ? ? get(){
? ? ? ? ? ? ? ? return _name;
????????}
})
|