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>