《深入理解ES6》阅读随笔
属性描述符陷阱
在 JavaScript 中,对象有 defineProperty 和 getOwnPropertyDescriptor 方法,分别用于自定义对象属性和获取对象属性信息;这两个方法在代理陷阱中也有相应的实现,并且接收参数也保持一致:
- defineProperty 接收三个参数
- trapTargat 目标对象;
- key 属性描述符键;
- value 属性描述符值;
- getOwnPropertyDescriptor 接收三个参数
- trapTargat 目标对象;
- key 属性描述符键;
默认用法
在默认情况下,代理陷阱转发了对象的 defineProperty 和 getOwnPropertyDescriptor 方法,功能看起来是没有变化的:
const targat = {}
const proxy = new Proxy(targat, {
defineProperty(trapTargat, key, descriptor) {
return Reflect.defineProperty(trapTargat, key, descriptor);
},
getOwnPropertyDescriptor(trapTargat, key) {
return Reflect.getOwnPropertyDescriptor(trapTargat, key);
}
})
Object.defineProperty(proxy, 'name', { value: 100 })
console.log(Object.getOwnPropertyDescriptor(proxy, 'name')) // { value: 100, writable: false, enumerable: false, configurable: false }
console.log(Object.getOwnPropertyDescriptor(targat,'name')) // { value: 100, writable: false, enumerable: false, configurable: false }
给 getOwnPropertyDescriptor 添加使用限制
可以在代理陷阱中,通过判断键的类型,来筛选一些满足条件的情况,然后拒绝其获取属性描述的权利:
const targat = {}
const proxy = new Proxy(targat, {
defineProperty(trapTargat, key, descriptor) {
if (descriptor)
return Reflect.defineProperty(trapTargat, key, descriptor);
},
getOwnPropertyDescriptor(trapTargat, key) {
// 拒绝获取字符串类型键的描述
if (typeof key === 'string') {
return false
}
return Reflect.getOwnPropertyDescriptor(trapTargat, key);
}
})
Object.defineProperty(proxy, 'name', { value: 100 })
console.log(Object.getOwnPropertyDescriptor(proxy, 'name')) // err
描述符对象限制
在使用 Object.defineProperty 定义属性时,第三个属性描述参数只允许接收含有 enumerable、writable、configurable 、value、get 和 set 属性的标准对象,否则无法执行成功,这个地方 Reflect.defineProProperty 也保持一致。
但是在使用 Object.getOwnPropertyDescriptor 时,存在一些差异,当在代理中返回非标准对象时,会报异常:
const proxy = new Proxy(targat, {
getOwnPropertyDescriptor(trapTargat, key) {
return {
value1:200
}
}
})
console.log(Object.getOwnPropertyDescriptor(targat, 'name')) // err
差异性
- defineProperty
Object.defineProperty 在执行成功后,会将第一个参数目标对象作为返回结果,而 Reflect.defineProperty 在执行成功后会返回 true,否则返回 false:
const targat = {value:1}
console.log(Object.defineProperty(targat, 'name', { value: 100 })) // {value:1}
console.log(Reflect.defineProperty(targat, 'name', { value: 100 })) // true
- getOwnPropertyDescriptor
Object. getOwnPropertyDescriptor 在第一个接收参数位置收到一个非对象类值时,会对其进行强制转换,因此返回一个 undefined 结果,而 Reflect.defineProperty 则会直接报异常:
console.log(Object.getOwnPropertyDescriptor(1, 'name')) // undefined
console.log(Reflect.getOwnPropertyDescriptor(1, 'name')) // err
网友评论