proxy
在中文里往往翻译成代理的意思,在JS中,它可以在对象间架设一层中间层,访问一个对象时需要先通过这一层:
var obj = new Proxy({}, {
get: function (target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function (target, key, value, receiver) {
console.log(`setting ${key}!`);
return Reflect.set(target, key, value, receiver);
}
});
可以看到和我们之前使用Object.defineProperty
来实现数据绑定很相似。
Proxy
是ES6中的新特性,它非常强大,但这里我们不详细解释,更多关于Proxy的内容可以参考这里。
首先我们来试一下简单的数据类型:
const person = {
name: 'jack',
age: 25,
info: {
prof: 'teacher',
city: 'beijng'
}
}
const observer = data => new Proxy(data, {
get(target, prop) {
console.log(`getting the ${prop}`)
return target[prop]
},
set(target, prop, value) {
console.log(`setting the ${prop} to ${value}`)
target[prop] = value
}
})
let proxy = observer(person)
效果如图:
可以看到这个效果和我们之前所使用的Object.defineProperty
所达成的是一样的。那么对于属性的值为数组和对象的复杂类型呢?
直接按上述的代码中的Proxy
实例来操作属性其实是不行的,但是我们可以对数组或对象类型的属性也代理一层:
const person = {
name: 'jack',
age: 25,
info: {
prof: 'teacher',
city: 'beijng'
},
children: ['lucy', 'lily', 'luc']
}
const observer = data => new Proxy(data, {
get(target, prop) {
console.log(`getting the ${prop}`)
return target[prop]
},
set(target, prop, value) {
console.log(`setting the ${prop} to ${value}`)
target[prop] = value
// 注意这里返回的true
return true
},
})
let proxy = observer(person)
let proxyChildren = observer(person.children)
此时我们对proxyChildren
进行操作,也是可以实现对数据的监听:
值得注意的是,之前如果set函数没有返回一个true
值,那么会抛出TypeError: 'set' on proxy: trap returned falsish for property '3'
错误,MDN上对这一点其实有记录:
Return value
The
set
method should return a boolean value. Returntrue
to indicate that assignment succeeded. If theset
method returnsfalse
, and the assignment happened in strict-mode code, aTypeError
will be thrown.
总结
结合上述的代码,我们已经可以使用proxy
来拦截一个对象的属性,以达成数据监听的目的,对于它的属性为复杂类型时,也只需要再次将其包装为一个proxy
实例。
下一篇我们再继续深入来尝试实现数据和视图的双向绑定。