概述
Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。
现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。
//ES5写法
try{
Object.defineProperty(target,property,attributes);
//success
} catch(e){
//failure
}
//ES6写法
if(Reflect.defineProperty(target,property,attributes)){
//success
}else{
//failure
}
//ES5写法
Function.prototype.apply.call(Math.floor,undefined,[1.75]) //1
//ES6写法
Reflect.apply(Math.floor,undefined,[1.75]) //1
Reflect.get(target, name, receiver)
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
如果name属性部署了读取函数(getter),则读取函数的this绑定receiver。
var myObject = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
},
};
var myReceiverObject = {
foo: 4,
bar: 4,
};
Reflect.get(myObject, 'baz', myReceiverObject) // 8
第一个参数不是对象,Reflect.get方法会报错。
Reflect.get(1, 'foo') // 报错
Reflect.get(false, 'foo') // 报错
Reflect.set(target, name, value, receiver)
Reflect.set方法设置target对象的name属性等于value值。
var myObject = {
foo:1,
set bar(value){
return this.foo = value;
}
}
myObject.foo //1
Reflect.set(myObject,'foo',2);
myObject.foo //2
Reflect.set(myObject,'bar',3);
myObject.foo //3
如果name属性设置了赋值函数,则赋值函数的this绑定receiver。
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
如果第一个参数不是对象,Reflect.set会报错。
Reflect.set(1, 'foo', {}) // 报错
Reflect.set(false, 'foo', {}) // 报错
Reflect.has(obj, name)
Reflect.has方法对应name in obj里面的in运算符。
var myObject = {
foo:1,
}
//ES5写法
'foo' in myObject //true
//ES6写法
Reflect.has(myObject,'foo')
Reflect.construct(target,args)
Reflect.construct方法等同于new target(…args),这提供了一种不使用new,来调用构造函数的方法。
function Greeting(name){
this.name = name;
}
//new的写法
const instance = new Greeting('阿蔡');
//Reflect.construct写法
const instance = Reflect.construct(Greeting,['阿蔡']);
Reflect.getPrototypeOf(obj)
Reflect.getPrototypeOf方法用于读取对象的_proto_属性,对应Object.getPrototypeOf(obj)。
const myObj = new FancyThing();
//ES5写法
Object.getPrototypeOf(myObj) === FancyThing.prototype;
//ES6写法
Reflect.getPrototypeOf(myObj) === FancyThing.prototype;
Reflect.getPrototypeOf和Object.getPrototypeOf的一个区别是,如果参数不是对象,Object.getPrototypeOf会将这个参数转为对象,然后再运行,而Reflect.getPrototypeOf会报错。
Object.getPrototypeOf(1) // Number {[[PrimitiveValue]]: 0}
Reflect.getPrototypeOf(1) // 报错
Reflect.setPrototypeOf(obj, newProto)
Reflect.setPrototypeOf方法用于设置对象的_proto_属性,返回第一个参数对象,对应Object.setPrototypeOf(obj, newProto)。
const myObj = new FancyThing();
//ES5写法
Object.setPrototypeOf(myObj,OtherThing.prototyype);
//ES6写法
Reflect.setPrototypeOf(myObj,OtherThing.prototyype);
如果第一个参数不是对象,Object.setPrototypeOf会返回第一个参数本身,而Reflect.setPrototypeOf会报错。
Object.setPrototypeOf(1, {})
// 1
Reflect.setPrototypeOf(1, {})
// TypeError: Reflect.setPrototypeOf called on non-object
如果第一个参数是undefined或null,Object.setPrototypeOf和Reflect.setPrototypeOf都会报错。
Object.setPrototypeOf(null, {})
// TypeError: Object.setPrototypeOf called on null or undefined
Reflect.setPrototypeOf(null, {})
// TypeError: Reflect.setPrototypeOf called on non-object
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 ages = [11, 33, 12, 54, 18, 96];
// ES5写法
const youngest = Math.min.apply(Math, ages);
const oldest = Math.max.apply(Math, ages);
const type = Object.prototype.toString.call(youngest);
// ES6写法
const youngest = Reflect.apply(Math.min, Math, ages);
const oldest = Reflect.apply(Math.max, Math, ages);
const type = Reflect.apply(Object.prototype.toString, youngest, []);
Reflect.defineProperty(target, propertyKey, attributes)
Reflect.defineProperty方法基本等同于Object.defineProperty,用来为对象定义属性。
function MyDate() {
/*…*/
}
// ES5写法
Object.defineProperty(MyDate, 'now', {
value: () => new Date.now()
});
// ES6写法
Reflect.defineProperty(MyDate, 'now', {
value: () => new Date.now()
});
如果Reflect.defineProperty的第一个参数不是对象,就会抛出错误,比如Reflect.defineProperty(1, ‘foo’)。
Reflect.getOwnPropertyDescriptor(target, propertyKey)
Reflect.getOwnPropertyDescriptor基本等同于Object.getOwnPropertyDescriptor,用于得到指定属性的描述对象。
var myObject = {};
Object.defineProperty(myObject, 'hidden', {
value: true,
enumerable: false,
});
// ES5写法
var theDescriptor = Object.getOwnPropertyDescriptor(myObject, 'hidden');
// ES6写法
var theDescriptor = Reflect.getOwnPropertyDescriptor(myObject, 'hidden');
Reflect.getOwnPropertyDescriptor和Object.getOwnPropertyDescriptor的一个区别是,如果第一个参数不是对象,Object.getOwnPropertyDescriptor(1, ‘foo’)不报错,返回undefined,而Reflect.getOwnPropertyDescriptor(1, ‘foo’)会抛出错误,表示参数非法。
Reflect.isExtensible (target)
Reflect.isExtensible方法对应Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展。
const myObject = {};
// ES5写法
Object.isExtensible(myObject) // true
// ES6写法
Reflect.isExtensible(myObject) // true
如果参数不是对象,Object.isExtensible会返回false,因为非对象本来就是不可扩展的,而Reflect.isExtensible会报错。
Object.isExtensible(1) // false
Reflect.isExtensible(1) // 报错
Reflect.preventExtensions(target)
Reflect.preventExtensions对应Object.preventExtensions方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。
var myObjet = {};
//ES5写法
Object.isExtensible(myObject) //true
//ES6写法
Reflect.preventExtensions(1) //true
如果参数不是对象,Object.isExtensible在 ES5 环境报错,在 ES6 环境返回这个参数,而Reflect.preventExtensions会报错。
// ES5
Object.preventExtensions(1) // 报错
// ES6
Object.preventExtensions(1) // 1
// 新写法
Reflect.preventExtensions(1) // 报错
Reflect.ownKeys (target)
Reflect.ownKeys方法用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和。
var myObject = {
foo:1,
bar:2,
[Symbol.for('baz')]:3,
[Symbol.for('bing')]:4
};
//ES5写法
Object.getOwnPropertyNames(myObject) //['foo', 'bar']
Object.getOwnPropertySymbols(myObject)
//[Symbol.for('baz'), Symbol.for('bing')]
// ES6写法
Reflect.ownKeys(myObject)
// ['foo', 'bar', Symbol.for('baz'), Symbol.for('bing')]