美文网首页日常刻书
一些常用的代理陷阱函数(二)

一些常用的代理陷阱函数(二)

作者: F_wind | 来源:发表于2021-02-15 09:31 被阅读0次

《深入理解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

相关文章

网友评论

    本文标题:一些常用的代理陷阱函数(二)

    本文链接:https://www.haomeiwen.com/subject/kfrpxltx.html