Proxy:代理器,改变对象的默认访问行为;在对象的访问行为之前增设拦截,通过Proxy实例进行的访问行为都必须经过设置的拦截;在拦截中可以根据需要 设置拦截条件
p()为自定义函数,后文中的p()都是调用这个函数
let p = function(){
console.log(...arguments);
}
目录
拦截器 | 作用 |
get | 拦截对象属性的读取,如obj.key,obj['key'],返回属性值 |
set | 拦截属性的设置,返回布尔值 |
has | 拦截key in obj的操作,返回布尔值 |
ownKeys | 拦截遍历如: for in 循环 |
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
对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'));
Object.definePrototype(obj,属性名,callback);
let obj = {};
let _name = '';
Object.definePrototype(obj,'name',{
set(val){
_name = val;
},
get(){
return _name;
}
})