Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。
设计目的
将原本定义在Object内部的方法移动到Refelect
之前defineProperty是定义在object对象下面Object.defineProperty,现在为什么要定义在Reflect对象下面呢?
JS设计之初将很多方法设计在了Object对象下面,这样设计并不合理,将来也会有很多的方法从Object转移到Reflect上
// 之前的写法
Object.defineProperty(...)
// 现在的写法
let obj = {}
let newValue = ''
Reflect.defineProperty(obj,'name',{
get(){
console.log('get')
return newValue
},
set(val){
console.log('set');
newValue = val
}
})
obj.name = 'ES6'
console.log(obj.name);
修改某些Object方法的返回结果,让其变得合理
eg: 在使用Object.defineProperty来定义对象上的某些属性的时候,有时候某些属性无法定义时就会报出异常,以前的写法就是放在try ... catch...中,因为Object.defineProperty没有返回值
try{
Object.defineProperty
}catch(e) {
console.log(e.message)
}
现在由于Reflecect.defineProperty()返回值是boolean,也就是将原先定义在Object上的defineProperty方法的返回值进行了改变,,让其变得合理
现在的写法:
if( Reflecect.defineProperty()){ // boolean
} else {
}
让Object操作变成函数行为
之前Object的很多操作都是命令式的
console.log('assign' in Object); // true
现在变成Reflect这种函数式
console.log(Reflect.has(Object,'assign')); // true
Reflect对象的方法与Proxy对象的方法一一对应
eg: 对象中以_开头的属性,希望对外界隐藏,变成对象的私有属性,不管是get、set、delete还是遍历都是不允许的
现在改成Reflect的写法:
原先用什么钩子函数进行拦截,现在改成这种形式
Reflect.对应的钩子函数
let user = {
name: 'lee',
age: 32,
_password: 'xxx'
}
user = new Proxy(user, {
get(target, prop) {
if (prop.startsWith('_')) {
throw new Error('私有属性不可访问')
} else {
// return target[prop]
return Reflect.get(target, prop)
}
},
// 对于set一定要返回布尔类型的值
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(item => !item.startsWith('_'))
return Reflect.ownKeys(target).filter(item => !item.startsWith('_'))
}
})
// 测试用例
//console.log(user._password); // 私有属性不可访问
// console.log(user.name); // lee
// user.age = 18
// console.log(user.age); // 18
// try {
// user._password = 8888
// } catch (e) {
// console.log(e.message); // 私有属性不可访问
// }
// try {
// delete user.age
// } catch (e) {
// console.log(e.message);
// }
// console.log(user.age); // undefined
// for(key in user) {
// console.log(key); // name age _password是被保护的属性
// }
eg: 将apply拦截器方法改成Reflect的形式
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