《深入理解ES6》阅读随笔
在介绍代理陷阱函数之前,先来看一个简单的代理例子:
const targat = {}
const proxy = new Proxy(targat, {})
targat.name = 'Hi,man!'
console.log('change targat (targat)', targat)
console.log('change targat (proxy)', proxy)
proxy.name = 'Hi,man,too!'
console.log('change proxy (targat)', targat)
console.log('change proxy (proxy)', proxy)
// 输出
// change targat (targat) { name: 'Hi,man!' }
// change targat (proxy) { name: 'Hi,man!' }
// change proxy (targat) { name: 'Hi,man,too!' }
// change proxy (proxy) { name: 'Hi,man,too!' }
上的例子中,proxy 转发代理了 targat 对象的全部操作,因此 proxy 会随着 targat 的改变而改变。
使用 set 陷阱函数验证属性
set 陷阱函数可以在赋值之前校验属性值是否满足条件,如果满足则完成赋值,否则拒绝之。下面是一个验证新属性是否为数字的的代理:
const targat = {
name: 'Hi,man!'
}
const proxy = new Proxy(targat, {
set(targatProxy, key, value, receiver) {
if (!targatProxy.hasOwnProperty(key)) {
if (isNaN(value)) {
throw new Error('not number!')
}
}
return Reflect.set(targatProxy, key, value, receiver)
}
})
// 设置数字
proxy.count = 1
console.log(targat)
console.log(proxy)
// 修改原有属性
proxy.name = 'Hi,man,too!'
console.log(targat)
console.log(proxy)
// 设置字符串
proxy.value = 'Good'
console.log(targat)
console.log(proxy)
// 输出
// { name: 'Hi,man!', count: 1 }
// { name: 'Hi,man!', count: 1 }
// { name: 'Hi,man,too!', count: 1 }
// { name: 'Hi,man,too!', count: 1 }
// Err
set 接收四个参数:
- targatProxy 目标对象;
- key 要写入的键;
- value 要写入的值;
- receiver 代理;
使用 get 陷阱函数验证对象结构(object shape)
在原生 JavaScript 中读取对象属性时,如果不存在该属性名,此时不会返回异常,而是返回一个 undefined 值,这种用法容易埋下一些隐患,不是很安全。在 ES6 中,可以使用 get 代理的方式,来对读取操作做一个代理,使数据读取更加安全规范:
const targat = {
name: 'Hi,man!'
}
const proxy = new Proxy(targat, {
get(targatProxy, key, receiver) {
if (!(key in receiver)) {
throw new Error('there is no key!')
}
return Reflect.get(targatProxy, key, receiver)
}
})
// 普通对象
console.log(targat.name) // 正常读取 Hi,man!
console.log(targat.nme) // 异常读取 undefined
// 代理对象
console.log(proxy.name) // 正常读取 Hi,man!
console.log(proxy.nme) // err
get 接收三个参数:
- targatProxy 目标对象;
- key 要读取的键;
- receiver 代理;
使用 has 陷阱函数隐藏已有属性
使用 has 陷阱函数可以隐藏一些不愿意被 in 到的属性:
const targat = {
name: 'Hi,man!',
value: 'hide'
}
const proxy = new Proxy(targat, {
has(targatProxy, key) {
if (key === 'value') {
return false
} else {
return Reflect.has(targatProxy, key)
}
}
})
// 普通对象
console.log('name' in targat) // true
console.log('value' in targat) // true
// 代理对象
console.log('name' in proxy) // true
console.log('value' in proxy) // false
has 接收两个参数:
- targatProxy 目标对象;
- key 要读取的键;
使用 deleteProperty 陷阱函数禁止删除指定属性
使用 deleteProperty 陷阱函数可以避免被保护的属性被意外删除:
const targat = {
name: 'Hi,man!',
value: 'hide'
}
const proxy = new Proxy(targat, {
deleteProperty(targatProxy, key) {
if (key === 'value') {
throw new Error('value can not be deleted!')
} else {
return Reflect.deleteProperty(targatProxy, key)
}
}
})
// 普通对象
delete targat.value
console.log('value' in targat) // false
console.log(targat.value) // undefined
// 代理对象
delete proxy.value
console.log('name' in proxy) // err
console.log(proxy.value) // err
deleteProperty 接收两个参数:
- targatProxy 目标对象;
- key 要读取的键;
网友评论