文章目录
一、Reflect概述
Reflect 对象与 Proxy 对象一样,也是 ES6 为了操作对象而提供的新 API。 Reflect 对象的设计目的及特点:
- 将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty ),放到 Reflect对象上。
现阶段,某些方法同时在 Object 和Reflect 对象上部署,未来的新方法将只部署在Reflect 对象上。也就是说,从Reflect 对象上可以拿到语言内部的方法。 - 修改某些 Object 方法的返回结果,让其变得更合理。
比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc) 则会返回 false。 - 让Object操作变成函数行为
-某些 Object 操作是命令式,比如 name in obj 和 delete obj[name] ,而 Reflect.has(obj, name) 和Reflect.deleteProperty(obj, name) 让它们变成了函数行为。 - Reflect对象的方法与Proxy对象的方法一一对象
只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。这就让 Proxy 对象可以方便 地调用对应的 Reflect 方法,完成默认行为,作为修改行为的基础。也就是说,不管 Proxy 怎么修改默认行为,你总可以在 Reflect 上获取默认行为。
二、用法详解
1.Object -> Reflect
Object.defineProperty可用Reflect.defineProperty代替
let obj = {}
let newVal = ''
Reflect.defineProperty(obj, 'name', {
get() {
return newVal
},
set(val) {
console.log('set') // set
// this.name = val
newVal = val
}
})
obj.name = 'es'
console.log(obj.name) // es
2. 修改Object方法的返回结果
// ES5的写法,无法自己抛出错误,需要放在try-catch里面
try {
Object.defineProperty()
} catch (e) {}
// ES6
if (Reflect.defineProperty()) { // boolean
} else {
}
3. 命令式操作->函数式操作
// 判断对象是否有assign方法
// ES5命令式
console.log('assign' in Object) // true
// ES6函数式
console.log(Reflect.has(Object, 'assign'))// true
4. 与Proxy对象的方法一一对象
//保护下划线属性
let user = {
name: 'kaka',
age: 20,
_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) // undefined
for (let key in user) {
console.log(key) // name
}
5. apply
// 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)) // 6
console.log(sum.call(null, 1, 2, 3)) // 12
console.log(sum.apply(null, [1, 2, 3])) // 12
总结
Reflect的出现是为了让Object方法更加规范。