Reflect 是 js 的一个内置对象,类似 Math,Date,实现一些和对象内部的方法同样的功能,分别有getPrototypeOfsetPrototypeOfisExtensiblepreventExtensionsgetOwnPropertyDescriptordefinePropertyhasgetsetdeletePropertyownKeysapplycall

虽然 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
// es6
function 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); // 123
console.log(obj1.name); // 123
var res = Reflect.defineProperty(obj, 'name', {
enumerable: true,
value: 321,
});
console.log(obj.name); // 321
console.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); // undefined
var 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] }