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

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

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

    《深入理解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 接收四个参数:

    1. targatProxy 目标对象;
    2. key 要写入的键;
    3. value 要写入的值;
    4. 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 接收三个参数:

    1. targatProxy 目标对象;
    2. key 要读取的键;
    3. 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 接收两个参数:

    1. targatProxy 目标对象;
    2. 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 接收两个参数:

    1. targatProxy 目标对象;
    2. key 要读取的键;

    相关文章

      网友评论

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

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