Proxy
监听对象的操作
vue2中响应式原理的核心代码(ES5之前)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21const obj = {
name: "beichen",
age: 22,
height: 1.75
}
for (const key in obj) {
let value = obj[key]
// 存取属性描述符
Object.defineProperty(obj, key, {
set(newValue) {
console.log(`监听: ${key}属性的改变: ${newValue}`)
value = newValue
},
get() {
console.log(`监听: 获取${key}属性的值`)
return value
}
})
}
console.log(obj.name)
obj.name = "haixia"缺点:
get
get() {}有三个参数
- target:被监听的对象(此处的obj)
- property:被获取属性的key
- receiver:被调用的代理对象(objProxy)
set
set() {}有四个参数
- target:被监听的对象(此处的obj)
- property:将要设置属性的key
- value:新属性值
- receiver:被调用的代理对象(objProxy)
1 | const obj = { |
**tips:**对obj的操作是不会被监听到的,在代理对象中设置新的属性值也是没问题的。如果我们不去重写get/set方法,也是可以完成响应式的获取和设置,但是当我们重写get/set之后,我们需要额外的做一些操作,就需要我们自己完成对应的事情,比如get返回对应的值,set设置新的值等。
其他捕获器的监听方法
deleteProperty(删除)
has(key in tartget)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function foo(num1, num2) {
console.log(this, num1, num2)
}
const fooProxy = new Proxy(foo, {
apply(target, thisArg, otherArgs) {
console.log("监听了apply操作")
target.apply(thisArg, otherArgs)
},
construct(target, argArray, newTarget) {
console.log("---" + target, argArray, newTarget)
return new target(...argArray)
}
})
fooProxy.apply("abc", ['111', '222'])
new fooProxy('111', '222')apply(foo.apply())
construct(new fooProxy())
Reflect
Reflect和Proxy共同完成
好处:
- 转而间接的去操作对象,这也是代理对象的目的
- Reflect的捕获器和Proxy是一一对应的,且有返回值,对于代码的角度来说更加的严谨
- 好处三:
- receiver就是外层的Proxy对象
- Reflect.set/get的最后一个参数可以决定对象访问器中的setter/getter中的this指向
1 | const obj = { |
reflect结合construct的使用:
1 | function Person(name, age) { |