《深入理解ES6》阅读随笔
原型代理陷阱
在 ES6 新增的 setPrototypeOf 和 ES5 中原来就有的 getPrototypeOf 目前都支持原型代理,但是在使用时,有一些限制规则需要注意:其中 getPrototypeOf 只能返回对象或者 null,否则会报异常,setPrototypeOf 只要返回 false 就会报异常。
这是一个正常使用原型的例子:
const targat = {}
const targatPrototype = Object.getPrototypeOf(targat)
console.log(targatPrototype === Object.prototype) // true
Object.setPrototypeOf(targat, { a: 1 })
console.log(Object.getPrototypeOf(targat)) // {a: 1}
下面分别是 getPrototypeOf 和 setPrototypeOf 使用代理陷阱并且触发限制规则的例子:
getPrototypeOf:
const targat = {}
const proxy = new Proxy(targat, {
getPrototypeOf(targatProxy) {
return 1
}
})
const proxyPrototype = Object.getPrototypeOf(proxy) // err
setPrototypeOf:
const targat = {}
const proxy = new Proxy(targat, {
setPrototypeOf(targatProxy, proto) {
return false
}
})
Object.setPrototypeOf(proxy, { a: 1 }) // err
除了使用限制,原型和原型代理陷阱用法几乎是一致的,这是一个使用原型代理陷阱默认方法的例子:
const targat = {}
const proxy = new Proxy(targat, {
getPrototypeOf(targatProxy) {
return Reflect.getPrototypeOf(targatProxy)
},
setPrototypeOf(targatProxy, proto) {
return Reflect.setPrototypeOf(targatProxy,proto)
}
})
const proxyPrototype = Object.getPrototypeOf(proxy)
console.log(proxyPrototype === Object.prototype) // true
Object.setPrototypeOf(proxy, { a: 1 })
console.log(Object.getPrototypeOf(proxy)) // {a: 1}
原型和原型代理陷阱的区别:
两者除了原型代理陷阱有使用限制外,其本质也是不同的。原型方法本身就是 JavaScript 中的一种高级操作,是面向开发者的,而且在调用方法传参时,如果传入的是非对象参数,原型方法会自动将其强制转化为对象而不报异常。而原型代理陷阱是 JavaScript 中的一种底层操作,在接收参数时不会自动转化,如果不是对象参数则会报异常。
对象可扩展性代理陷阱
对象可扩展方法有 preventExtensions 和 isExtensible 两个;其中 preventExtensions 的功能是改变对象的可扩展状态,然后返回布尔值作为结果,true 代表成功,false 代表失败;isExtensible 的功能是获取对象的可扩展性状态,true 代表可扩展,false 代表不可扩展。
这两个方法目前都支持代理,用法如下所示:
let targat = {}
let proxy = new Proxy(targat, {
preventExtensions(trapTargat) {
return Reflect.preventExtensions(trapTargat)
},
isExtensible(trapTargat) {
return Reflect.isExtensible(trapTargat)
}
})
console.log(Object.isExtensible(targat)) // true
console.log(Object.isExtensible(proxy)) // true
Object.preventExtensions(proxy)
console.log(Object.isExtensible(targat)) // false
console.log(Object.isExtensible(proxy)) // false
在代理陷阱中,可以做一些操作来阻止默认行为,比如禁止获取对象的可扩展状态:
let targat = {}
let proxy = new Proxy(targat, {
isExtensible(trapTargat) {
return false
}
})
console.log(Object.isExtensible(targat)) // err
console.log(Object.isExtensible(proxy))
还可以禁用修改对象的可扩展属性:
let targat = {}
let proxy = new Proxy(targat, {
preventExtensions(trapTargat) {
return false
}
})
console.log(Object.isExtensible(targat)) // true
console.log(Object.isExtensible(proxy)) // true
Object.preventExtensions(proxy)
console.log(Object.isExtensible(targat)) // err
console.log(Object.isExtensible(proxy))
对象可扩展性和对象可扩展性代理的差异:与原型一样,对象可扩展性也是高级操作,并且会对非对象参数进行强制转换;而和对象可扩展性代理则是底层操作,也不会强制转换参数,如果遇到非对象参数会报异常:
console.log(Object.isExtensible(1)) // false
console.log(Reflect.isExtensible(1)) // err
网友评论