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