ES6 | 反射Reflect

83 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

ES系列文章

Reflect和proxy的作用类似,也是代理拦截,但是Reflect主要面对的是内部语言的操作

  • 将Object对象属于语言内部的方法(比如Object.defineProperty)放到Reflect对象上。
//Object -> Reflect
let obj = {}
let newVal = ''
Reflect.defineProperty(obj, 'name', {
    get() {
        return newVal
    },
    set(val) {
        console.log('set')
        // this.name = val
        newVal = val
    }
})
obj.name = 'es'
console.log(obj.name)
  • 修改一些Object方法返回的结果,变得更合理。Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出错误,而Reflect.defineProperty(obj, name, desc)则会返回布尔值。
try {
    Object.defineProperty()
} catch (e) {}

if (Reflect.defineProperty()) { // boolean

} else {

}

  • 让Object操作都变成函数行为。某些Object操作是命令式。
console.log('assign' in Object) // true
console.log(Reflect.has(Object, 'assign'))// true
  • Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为。也就是说,不管Proxy怎么修改默认行为,都可以在Reflect上获取默认行为
let user = {
    name: 'xxx',
    age: 18,
    _password: '***'
}
user = new Proxy(user, {
    get(target, prop) {
        if (prop.startsWith('_')) {
            throw new Error('不可访问')
        } else {
            // return target[prop]
            return Reflect.get(target, prop)
        }
    },
    set(target, prop, val) {
        if (prop.startsWith('_')) {
            throw new Error('不可访问')
        } else {
            // target[prop] = val
            Reflect.set(target, prop, val)
            return true
        }
    },
    deleteProperty(target, prop) { // 拦截删除
        if (prop.startsWith('_')) {
            throw new Error('不可删除')
        } else {
            // delete target[prop]
            Reflect.deleteProperty(target, prop)
            return true
        }
    },
    ownKeys(target) {
        // return Object.keys(target).filter(key => !key.startsWith('_'))
        return Reflect.ownKeys(target).filter(key => !key.startsWith('_'))
    }
})

console.log(user.age)
try {
    console.log(user._password)
} catch (e) {
    console.log(e.message)
}

user.age = 18
console.log(user.age)
try {
    user._password = 'xxx'
} catch (e) {
    console.log(e.message)
}

// delete user.age
// console.log(user.age)
for (let key in user) {
    console.log(key)
}
// apply
let sum = (...args) => {
    let num = 0
    args.forEach(item => {
        num += item
    })
    return num
}

sum = new Proxy(sum, {
    apply(target, ctx, args) {
        // return target(...args) * 2
        return Reflect.apply(target, target, [...args]) * 2
    }
})
console.log(sum(1, 2))
console.log(sum.call(null, 1, 2, 3))
console.log(sum.apply(null, [1, 2, 3]))

一个前端小白,若文章有错误内容,欢迎大佬指点讨论!