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

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

作者: 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