Reflect 是 js 的一个内置对象,类似 Math,Date,实现一些和对象内部的方法同样的功能,分别有getPrototypeOf
,setPrototypeOf
,isExtensible
,preventExtensions
,getOwnPropertyDescriptor
,defineProperty
,has
,get
,set
,deleteProperty
,ownKeys
,apply
,call
等
虽然 Object.prototype.hasOwnProperty 内部实现了 hasOwnProperty 这个方法,但是不是创建的对象都有 hasOwnProperty 方法,如下
var myObject = Object.create(null);assert(myObject.hasOwnProperty === undefined);// 如果要hasOwnProperty方法,可以使用下面的语法Object.prototype.hasOwnProperty.call(myObject, 'foo');
Reflect 就是上述的内部方法的集合,使用起来更方便,下面介绍使用的方法
Reflect.apply(target, thisArgument [, argumentsList])
功能跟 Function#apply 一样
var ages = [11, 33, 12, 54, 18, 96];// Function方式var youngest = Math.min.apply(Math, ages);var oldest = Math.max.apply(Math, ages);var type = Object.prototype.toString.call(youngest);// Reflect方式var youngest = Reflect.apply(Math.min, Math, ages);var oldest = Reflect.apply(Math.max, Math, ages);var type = Reflect.apply(Object.prototype.toString, youngest);
使用 Function 方式有一个缺点就是方法有可能被重写
function test() { console.log(123);}test.apply(); // 123// 被重写test.apply = function () { console.log(321);};test.apply(null); // 321// 可以下面的方法Function.prototype.apply.call(test, null); // 123
Reflect.construct(target, argumentsList [, constructorToCreateThis])
Reflect.construct
相当于 new 操作符,用来实例化一个对象
function Greeting(name) { this.name = name;}Greeting.prototype.greet = function () { return `Hello ${this.name}`;};// es5可以使用这个方法来实例化function greetingFactory(name) { var instance = Object.create(Greeting.prototype); Greeting.call(instance, name); return instance;}var ins = greetingFactory('kelen');ins.greet(); // hello kelen// es6function greetingFactory2(name) { return Reflect.construct(Greeting, [name]);}var ins2 = greetingFactory2('kelen');ins2.greet(); // hello kelen
Reflect.construct
也可以用来实例化类
class Greeting { constructor(name) { this.name = name; } greet() { return `hello ${this.name}`; }}var ins = Reflect.construct(Greeting, ['kelen']);console.log(ins.greet());
Reflect.defineProperty(target, propertyKey, attributes)
功能类似于 Object.defineProperty,在为非对象添加属性的时候会抛出 TypeError,不同的是 Reflect.defineProperty 返回的是布尔值来判断是否成功定义,而 Object.defineProperty 返回的是一个对象,或者属性没有被成功定义,也会抛出 TypeError\
var obj = {};var obj1 = Object.defineProperty(obj, 'name', { configurable: true, // 可以重新定义 value: 123,});console.log(obj.name); // 123console.log(obj1.name); // 123var res = Reflect.defineProperty(obj, 'name', { enumerable: true, value: 321,});console.log(obj.name); // 321console.log(res); // true
Reflect.getOwnPropertyDescriptor(target, propertyKey)
功能与 Object.getOwnPropertyDescriptor 一样,返回给定的对象属性的属性描述符,不同的是如果 target 不是对象,Object.getOwnPropertyDescriptor 返回的是 undefined,而 Reflect.getOwnPropertyDescriptor 抛出 TypeError
var obj = {};Object.defineProperty(obj, 'name', { value: 'kelen', enumerable: false,});var desc = Reflect.getOwnPropertyDescriptor(obj, 'name');console.log(desc); // { value: 'kelen', writable: false, enumerable: false, configurable: false }var desc2 = Object.getOwnPropertyDescriptor(obj, 'name');console.log(desc2); // { value: 'kelen', writable: false, enumerable: false, configurable: false }var res = Object.getOwnPropertyDescriptor(1, 'foo');console.log(res); // undefinedvar res = Reflect.getOwnPropertyDescriptor(1, 'foo'); // 抛出错误
Reflect.deleteProperty(target, propertyKey)
类似于 delete 关键字,用来删除对象的属性
var myObj = { foo: 'bar' };delete myObj.foo;assert(myObj.hasOwnProperty('foo') === false);myObj = { foo: 'bar' };Reflect.deleteProperty(myObj, 'foo');assert(myObj.hasOwnProperty('foo') === false);
Reflect.getPrototypeOf(target)
功能同样类似 Object.getPropertyOf,不同的是 targt 不是对象的时候,Reflect.getPropertyOf 抛出 TypeError,而 Object.getProperty 返回 undefined
function Bird() { this.name = 'kelen';}Bird.prototype.say = function () { console.log(`hello ${this.name}`);};var b = new Bird();console.log(Object.getPrototypeOf(b)); // Bird { say: [function] }console.log(Reflect.getPrototypeOf(b)); // Bird { say: [function] }