Reflect对象
About
随着学习的深入,我逐渐对JavaScript有了更宏观的认识,之前在工作中遇到的一些问题也得到了解释,我觉得学习就是这样,从微观到宏观,总有一天我吃透Javascript的架构,请继续加油!
1. Reflect概述
Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。针对Reflect的设计目的来说,我觉得大概分为四点:
1.1 简化Object对象
从 ES2015 开始,官方有意识的去调整Javascript的架构,使得其结构更加清晰,比如将一些全局方法部署到专门的对象上,又如像Reflect对象一样,将大部分以前属于Object的静态方法移植到Reflect对象上,以后可能Object只承担构造函数的责任,即Object上只有实例方法,将更多的操作对象的方法部署到专门的对象Reflect上。
1.2 改变Object静态方法的行为
之前,Object的静态方法的行为不是很难统一,有的有返回值,有点没有返回值,有的返回一个对象实例,而有的又返回布尔值,很不规范,比如:
var a = {}
Object.setPrototypeOf(a, Array.prototype) // Array {}
Reflect.setPrototypeOf(a, Object.prototype) // true
Object.setPrototypeOf(1, Array.prototype) // 1
Reflect.setPrototypeOf(1, Object.prototype) // Uncaught TypeError
Reflect.setPrototypeOf(Object.freeze(a), Array.prototype) // false
通过上面的代码我们可以发现,Object.setPrototypeOf总是返回第一个参数,我们并不知道操作是成功了还是失败了,是合法的还是非法的;但是Reflect.setPrototypeOf就不一样了,它会返回一个布尔值来告诉你是成功还是失败,我们可以用if...else去进行不同的操作。
1.3 让Objct操作都变成函数式操作
Reflect对象的方法都是函数式操作,即接受参数并有返回值,而Object就不一样了:
var a = {
name: 'bing'
}
delete a.name // true
Reflect.deleteProperty(a, 'name') //true
变成函数式操作后,编程风格更严谨了
1.4 和Proxy一一对应
Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
2. 静态方法
Reflect大部分与Object对象的同名方法的作用都是相同的,而且它与Proxy对象的方法是一一对应的。这里只记录几个常见的,更多的方法请参阅原著。
2.1 get(target, name, recevier)
Reflect.get方法查找并返回target对象的name属性,如果没有该属性,则返回undefined。
var myObject = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
},
}
Reflect.get(myObject, 'foo') // 1
Reflect.get(myObject, 'bar') // 2
Reflect.get(myObject, 'baz') // 3
get方法接受的第三个参数receiver是当target对象中被读取的prop有setter方法的时候,setter的this可以绑定到reveiver
2.2 set(target, name, value, receiver)
Reflect.set()方法会设置target对象的name属性的值为value,如果name的属性设置了setter,那么setter的this就会绑定至rceivr
var myObject = {
foo: 4,
set bar(value) {
return this.foo = value;
},
};
var myReceiverObject = {
foo: 0,
};
Reflect.set(myObject, 'bar', 1, myReceiverObject);
myObject.foo // 4
myReceiverObject.foo // 1
2.3 has(obj, name)
该方法相当于in运算符
var myObject = {
foo: 1,
};
// 旧写法
'foo' in myObject // true
// 新写法
Reflect.has(myObject, 'foo') // true
2.4 defineProprty(targeet, name, attriDescObj)
Reflect.defineProperty方法基本等同于Object.defineProperty,用来为对象定义属性。未来,后者会被逐渐废除,请从现在开始就使用Reflect.defineProperty代替它。
function MyDate() {
/*…*/
}
// 旧写法
Object.defineProperty(MyDate, 'now', {
value: () => Date.now()
});
// 新写法
Reflect.defineProperty(MyDate, 'now', {
value: () => Date.now()
});
参考链接
作者:阮一峰
