Reflect是一个内建的对象,用来提供方法去拦截JavaScript的操作。Reflect不是一个函数对象,所以它是不可构造的,也就是说它不是一个构造器,你不能通过new操作符去新建或者将其作为一个函数去调用Reflect对象。Reflect的所有属性和方法都是静态的。
ReflectReflect对象最大的意义就是提供了一套统一操作Object的API,因为在这之前操作对象时都会使用Object对象上的方法,也有可能使用像delete或者是in这样的操作符。
Reflect对象就很好的解决了这样一个问题,他统一了对象的操作方式,我们可以通过几个简单的例子来看一下。
这里我们先定义一个obj对象,然后在对象当中定义了几个属性。按照传统的方式如果我们需要判断这个对象中是否存在某个属性,我们需要使用in这个语句,用到in操作符,删除属性需要使用到delete语句。而如果需要获取对象中所有的属性名,那需要使用Object.keys这样的方法。
const obj = {
a: 1,
b: 2,
c: 3
}
console.log('a' in obj); // true
console.log(delete obj['a']); // true
console.log(Object.keys(obj)); // ["b", "c"]
那也就是说我们同样都是去操作这个对象,但是我们一会需要用操作符的方式,一会又需要用到某一个对象当中的方法。
而Reflect就提供了一个统一的方式,当判断对象当中是否存在某一个属性可以使用Reflect.has方法。
console.log(Reflect.has(obj, 'b')); // true
console.log(Reflect.deleteProperty(obj, 'b')); // true
console.log(Reflect.ownKeys(obj)); // ["c"]
Reflect对象的方法Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为。
getReflect.get方法与从对象 (target[propertyKey]) 中读取属性类似,但它是通过一个函数执行来操作的。
Reflect.get(target, propertyKey[, receiver])
接收3个参数:
target: 目标对象, 如果不是对象,会报错propertyKey: 属性名receiver: 如果target对象中指定了getter,receiver则为getter调用时的this值。const obj = {
a: 1,
b: 2,
get c() {
return this.a + this.b;
}
}
const obj2 = {
a: 4,
b: 5
}
const arr = [1, '2', 'string'];
Reflect.get(obj, 'a') // 1
Reflect.get(arr, 2) // "string"
// c的getter中的this指向obj2
Reflect.get(obj, 'c', obj2) // 9
Reflect.get(1, 'a'); // Uncaught TypeError: Reflect.get called on non-object
set在对象上设置一个属性。
Reflect.set(target, propertyKey, value[, receiver])
接收4个参数:
target: 目标对象, 如果不是对象,会报错propertyKey: 属性名value: 值receiver: 如果target对象中指定了setter,receiver则为setter调用时的this值。const obj = {
a: 1,
set b(value) {
return this.a = value;
}
}
const obj2 = {
a: 4
}
Reflect.set(obj, 'c', 3); // true
obj.c // 3
Reflect.set(obj, 'b', 2) // true
obj.a // 2
Reflect.set(obj, 'b', 2, obj2); // true
obj2.a // 2
applyapply方法等同于Function.prototype.apply.call(func, thisArg, args),用于绑定this对象后执行给定函数。
一般来说,如果要绑定一个函数的this对象,可以这样写fn.apply(obj, args),但是如果函数定义了自己的apply方法,就只能写成Function.prototype.apply.call(fn, obj, args),采用Reflect对象可以简化这种操作。
Reflect.apply(target, thisArgument, argumentsList)
接收3个参数:
target: 目标函数thisArgument: 需要绑定的this对象argumentsList: 传入的参数列表(类数组对象)const ages = [11, 33, 12, 54, 18, 96];
// 旧写法
const youngest = Math.min.apply(Math, ages);
const oldest = Math.max.apply(Math, ages);
const type = Object.prototype.toString.call(youngest);
// 新写法
const youngest = Reflect.apply(Math.min, Math, ages);
const oldest = Reflect.apply(Math.max, Math, ages);
const type = Reflect.apply(Object.prototype.toString, youngest, []);
hashas 作用与 in 操作符相同。
Reflect.has(target, propertyKey)
接收2个参数
target: 目标对象,非Object类型会报错propertyKey: 属性名const obj = {
a: 1,
}
'a' in obj // true
Reflect.has(obj, 'a') // true
definePropertydefineProperty基本等同于 Object.defineProperty()方法,唯一不同是返回 Boolean 值。
Reflect.defineProperty(target, propertyKey, attributes)
接收3个参数:
target: 目标对象,非Object类型会报错propertyKey: 要定义或修改的属性的名称attributes: 要定义或修改的属性的描述。const obj = {};
Reflect.defineProperty(obj, 'a', {value: 1}) // true
obj.a // 1
getOwnPropertyDescriptorgetOwnPropertyDescriptor 与 Object.getOwnPropertyDescriptor、 方法相似。如果在对象中存在,则返回给定的属性的属性描述符。否则返回 undefined。
Reflect.getOwnPropertyDescriptor(target, propertyKey)
接收2个参数:
target: 目标对象,非Object类型会报错propertyKey: 属性名var obj = {};
Object.defineProperty(obj, 'a', {
value: 1,
enumerable: false,
});
Object.getOwnPropertyDescriptor(obj, 'a');
Reflect.getOwnPropertyDescriptor(obj, 'a');
getPrototypeOfgetPrototypeOf与 Object.getPrototypeOf 方法几乎是一样的。都是返回指定对象的原型。
Reflect.getPrototypeOf(target)
接收1个参数
target: 目标对象,非Object类型会报错Reflect.getPrototypeOf({}); // Object.prototype
Reflect.getPrototypeOf(Object.prototype); // null
Reflect.getPrototypeOf(Object.create(null)); // null
isExtensibleisExtensible判断一个对象是否可扩展(即是否能够添加新的属性)
Reflect.isExtensible(target)
接收1个参数
target: 目标对象,非Object类型会报错const obj = {};
Object.isExtensible(obj) // true
Reflect.isExtensible(obj) // true
如果参数不是对象,Object.isExtensible会返回false,因为非对象本来就是不可扩展的,而Reflect.isExtensible会报错。
ownKeysownKeys 返回一个由目标对象自身的属性键组成的数组。
Reflect.ownKeys(target)
接收1个参数
target: 目标对象,非Object类型会报错preventExtensionspreventExtensions 方法阻止新属性添加到对象 (例如:防止将来对对象的扩展被添加到对象中)。
Reflect.preventExtensions(target)
接收1个参数
target: 目标对象,非Object类型会报错const obj = {};
Object.preventExtensions(obj) // obj {}
Reflect.preventExtensions(obj) // true
setPrototypeOfsetPrototypeOf与 Object.setPrototypeOf 方法是一样的。它可设置对象的原型(即内部的 [[Prototype]] 属性)为另一个对象或 null,如果操作成功返回 true,否则返回 false。
Reflect.setPrototypeOf(target, prototype)
接收2个参数
target: 目标对象,非Object类型会报错prototype: 对象的新原型(一个对象或 null)const obj = {};
Object.setPrototypeOf(obj, Array.prototype);
Reflect.setPrototypeOf(obj, Array.prototype);