1、什么是Proxy?
Proxy 也就是代理,可以帮助我们完成很多事情,例如对数据的处理,对构造函数的处理,对数据的验证,说白了,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
语法
let p = new Proxy(target, handler);
参数
- target :需要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
- handler: 一个对象,其属性是当执行一个操作时定义代理的行为的函数
- proxy:是一个被代理后的新对象,它拥有target的一切属性和方法.只不过其行为和结果是在handler中自定义的
示例,一个简单的代理:
let test = {
name: "小明"
};
test = new Proxy(test, {
get(target, key) {
console.log('获取了getter属性');
return target[key];
}
});
console.log(test.name);
上方的案例,我们首先创建了一个test对象,里面有name属性,然后我们使用Proxy将其包装起来,再返回给test,此时的test已经成为了一个Proxy实例,我们对其的操作,都会被Proxy拦截。当我们对test对象查询时,就会进入我们写好的get函数,其他操作都是如此
使用set来拦截一些操作,并将get返回值更改
let xiaohong = {
name: "小红",
age: 15
};
xiaohong = new Proxy(xiaohong, {
get(target, key) {
let result = target[key];
//如果是获取 年龄 属性,则添加 岁字
if (key === "age") result += "岁";
return result;
},
set(target, key, value) {
if (key === "age" && isNaN(value)) {
throw Error("age字段必须为Number类型");
}
return Reflect.set(target, key, value);
}
});
console.log(`我叫${xiaohong.name} 我今年${xiaohong.age}了`);
xiaohong.age = "aa";
get 拦截函数中添加了一个判断,如果是取 age 属性的值,则在后面添加 岁。在 set 拦截函数中判断了如果是更改 age 属性时,类型不是 Number则抛出错误。
扩展 使用代理实现双向绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
<span>年龄:</span>
<input type="text" id="age" value="13">
</p>
</body>
<script>
const spanAge = document.getElementById("age");
let user = {
age:spanAge.value
}
let newuser = new Proxy(user,{
set(target, key, value){
if (key === "age" && isNaN(value)) {
throw Error("age字段必须为Number类型");
}
spanAge.value = value;
return Reflect.set(target, key, value);
}
})
spanAge.onblur = function(){
newuser.age = document.getElementById("age").value;
console.log(user);
}
console.log(user)
</script>
</html>