简单解释一下什么是钩子函数。当我们在操作一个对象或者方法时会有几种动作,比如:在运行函数前初始化一些数据,
在改变对象值后做一些善后处理。这些都算钩子函数,Proxy的存在就可以让我们给函数加上这样的钩子函数,你也可以理解为在执行方法前预处理一些代码。你可以简单的理解为他是函数或者对象的生命周期。Proxy的应用可以
使函数更加强大,业务逻辑更加清楚,而且在编写自己的框架或者通用组件时非常好用。Proxy涉及的内容非常多,那这里我就带你入门并且介绍给你后续的学习方法。
var obj={
add:function(val){
return val+10;
},
name:'I am Zachary'
};
console.log(obj.add(100));
console.log(obj.name);
声明了一个obj对象,增加了一个对象方法add和一个对象属性name,然后在控制台进行了打印。
声明Proxy
我们用new的方法对Proxy进行声明。可以看一下声明Proxy的基本形式。
需要注意的是这里是两个花括号,第一个花括号就相当于我们方法的主体,后边的花括号就是Proxy代理处理区域,相当于我们写钩子函数的地方。
var pro = new Proxy({
add: function (val) {
return val + 10;
},
name: 'I am Zachary'
}, {
get:function(target,key,property){
console.log('come in Get');
return target[key];
}
});
console.log(pro.name);
可以在控制台看到结果,先输出了come in Get。相当于在方法调用前的钩子函数。
get属性
get属性是在你得到某对象属性值时预处理的方法,他接受三个参数
target:得到的目标值
key:目标的key值,相当于对象的属性
property:这个不太常用,用法还在研究中,还请大神指教。
set属性
set属性是值你要改变Proxy属性值时,进行的预先处理。它接收四个参数。
target:目标值。
key:目标的Key值。
value:要改变的值。
receiver:改变前的原始值。
var pro = new Proxy({
add: function (val) {
return val + 10;
},
name: 'I am Zachary'
}, {
get:function(target,key){
console.log('come in Get');
return target[key];
},
set:function(target,key,value,receiver){
console.log(`setting ${key} = ${value}`);
return target[key] = value;
}
});
console.log(pro.name);
pro.name='齐轩';
console.log(pro.name);
apply的使用
apply的作用是调用内部的方法,它使用在方法体是一个匿名函数时。看下边的代码。
let target = function () {
return 'I am Zachary';
};
var handler = {
apply(target, ctx, args) {
console.log('do apply');
return Reflect.apply(...arguments);
}
}
var pro = new Proxy(target, handler);
console.log(pro());
栗子
// 商演模拟
// 某人(换成娱乐圈那就是明星)
let star = {
name: "齐轩",
age: 25,
phone: "star:15817594823",
price: "保密", //可写可不写 在get中都会拦截
};
// 代理(换成娱乐圈 那这里的代理就是经纪人)
let agent = new Proxy(star, {
get: function(target, key) {
// target是star的对象内容 key则是你要拦截的
/* 其实 star 里面的phone和price也可以你不写会自动拦截 匹配到下面的if*/
if (key === "phone") {
// 返回经纪人自己的手机号
return "agent:15517594453";
}
if (key === "price") {
// 明显不报价 经纪人报价
return 12000;
}
return target[key];
},
set: function(target, key, val) {
if (key === "customPrice") {
// 设置明星价格
if (val < 10000) {
throw new Error("价格太低");
// console.log("价格太低");
} else {
target[key] = val;
return true; // 不写return true 不会赋值成功
}
}
},
});
// test
console.log(agent.name);
console.log(agent.age);
console.log(agent.phone); //获取到的是get中拦截的手机号(也就是代理人/经纪人的)
console.log(agent.price); //获取到的是get中拦截的价格
// agent.customPrice = 120000; // 设置给明星的价格 如果这里写的价格小于上面设置的10000则会报错说价格太低
// console.log(agent.customPrice); // 打印出120000
agent.customPrice = 1200; // 如果这里写的价格小于上面设置的10000则会报错说价格太低
console.log(agent.customPrice); // 打印出价格太低