Reflect是ES6为了操作对象而提供的新的API。 其目的为下: 1:将Object对象的一些明显属于语言内部的方法,放到Reflect上,
比如(Object.defineProperty)。值得注意的是未来的新方法会部署到Reflect上。
2:修改某些Object方法的返回结果,让其更加合理。
比如:
Object.defineProperty(obj,name,val)如果无法定义属性时会报错,
而Reflect.defineProperty(obj,name,val)会返回false
3:让Object操作都变成函数行为。
比如:delete,in等,
往常写法:delete obj[name],'assign' in obj
Reflect写法:Reflect.has(obj,'assign')
4: Reflect上的方法与Proxy对象的方法一一对应,
只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。
这样做的好处是:
Proxy可以方便的调用对应的Reflect对象上的方法。完成Proxy本意的默认行为。
比如:
Proxy(target, {
set: function(target, name, value, receiver) {
var success = Reflect.set(target, name, value, receiver);
if (success) {
console.log('property ' + name + ' on ' + target + ' set to ' + value);
}
return success;
}});
其中:
我们在Proxy的元编程的方式,修改target对象上的访问器属性set,
在es6之前我们只能通过Object.defineProperty()来定义,
而现在我们可以通过Proxy的set来定义,那么与之对应,在set中,可通过Reflect.set来完成对应的Proxy中set本意的默认行为
5: 有了Reflect之后,操作更易读
比如:
// 老写法
Function.prototype.apply.call(Math.floor, undefined, [1.75]) // 1
// 新写法
Reflect.apply(Math.floor, undefined, [1.75]) // 1
目前Reflect一共有13个静态方法
Reflect.apply(target, thisArg, args)
Reflect.construct(target, args)
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.defineProperty(target, name, desc)
Reflect.deleteProperty(target, name)
Reflect.has(target, name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)
下面摘取几个常用的Reflect静态方法
1)Reflect.apply(func, thisArg, args)
Reflect.apply方法等同于Function.prototype.apply.call(func, thisArg, args),
用于绑定this对象后执行给定函数。
一般来说,如果要绑定一个函数的this对象,
可以这样写fn.apply(obj,args),
但是如果函数定义了自己的apply方法,
就只能写成Function.prototype.apply.call(fn,obj,args),
采用Reflect对象可以简化这种操作。
比如:
// 旧写法
const youngest = Math.min.apply(Math,[1,2,3,4,5,6])
// 新写法
const youngest = Reflect.apply(Math.min,Math,[1,2,3,4,5,6])
其中:Math 对象是用于执行数学任务的系统内置对象。
2)Reflect.get(target,name,receiver)
Reflect.get方法查找并返回target对象的name属性,如果没有属性,则返回undefined。
tips:如果第一个参数不传对象,则会报错
如果target对象中指定了getter,receiver则为getter调用时的this值。
tips:
1:如果属性没有指定getter,那么无论传不传第三个参数,返回的都是第一个对象的属性的值
2:如果属性指定getter,但是不传第三个参数,返回的是第一个对象的属性的值
3)Reflect.set(target, name, value, receiver) Reflect.set方法设置target对象的name属性等于value。 如果name属性设置了赋值函数,则赋值函数的this绑定receiver
如果Proxy.set拦截里面使用了Reflect.set,而且传入了receiver,导致触发Proxy.defineProperty拦截。这是因为Proxy.set的receiver参数总是指向当前的Proxy实例(即上例的obj),
而Reflect.set一旦传入receiver,就会将属性赋值到receiver上面(即obj),
导致触发defineProperty拦截。如果Reflect.set没有传入receiver,那么就不会触发defineProperty拦截。
4):Reflect.has(obj, name)
Reflect.has方法对应name in obj里面的in运算符。
5):Reflect.deleteProperty(obj,name)
Reflect.deleteProperty方法对应delete obj name
6):Reflect.construct
Reflect.construct方法相当于new target(),提供一种不使用new,来调用构造函数的方法。
function Greeting(name){
this.name= name
}
// new 写法
const instance = new Greeting("张三")
// reflect写法
const instance = Reflect.construct(Greeting,['张三'])
tips:这里传的第一个参数,是一个构造函数
7):Reflect.getPrototypeOf(obj)
Reflect.getPrototypeOf方法用于读取对象的__proto__属性(隐式原型对象),
对应Object.getPrototypeOf(obj)。
tips:
Reflect.getPrototypeOf和Object.getPrototypeOf的一个区别是,
如果参数不是对象,Object.getPrototypeOf会将这个参数转为对象,然后再运行,
而Reflect.getPrototypeOf会报错。
8):Reflect.setPrototypeOf(obj, newProto) Reflect.setPrototypeOf方法用于设置目标对象的原型(prototype)(显式原型对象), 对应Object.setPrototypeOf(obj, newProto)方法。 它返回一个布尔值,表示是否设置成功。
tips:
1:如果无法设置目标对象的原型(比如,目标对象禁止扩展),Reflect.setPrototypeof返回false
2:如果第一个参数不是对象,Object.setPrototypeOf会返回第一个参数本身,而Reflect.setPrototypeOf会报错。
3:如果第一个参数是undefined或null,Object.setPrototypeOf和Reflect.setPrototypeOf都会报错。