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] }