ES6篇 - Reflect
Reflect
概念
Reflect 对象: ES6 为操作对象而提供的新 API, 用于替代 Object 的一些操作方法:
- 将Object对象的一些明显属于语言内部的方法(比如
Object.defineProperty
),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。
- 修改某些Object方法的返回结果,让其变得更合理。比如,
Object.defineProperty(obj, name, desc)
在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)
则会返回false
。1
2
3
4
5
6
7
8
9
10
11
12
13
14// Object.defineProperty()
try {
Object.defineProperty(target, property, attributes);
// success
} catch (err) {
// failure
}
// Reflect.defineProperty()
if (Reflect.defineProperty(target, property, attributes)) {
// success
} else {
// failure
} - 统一所有 Object 操作为函数式行为;
例如:
name in obj
,delete obj[name]
等 Object 操作是命令式的, 现用 Reflect 将其统一成函数式,Reflect.has(obj, name)
,Reflect.deleteProperty(obj, name)
1
2
3
4
5// 命令式 Object 操作
'assign' in obj;
// 函数式 Object 操作
Reflect.has(obj, 'assign'); - Reflect 对象方法与 Proxy 对象方法一一对应; 使得 Proxy 对象可以方便调用 Reflect 对象方法, 完成默认行为, 作为修改行为的基础; 无论 Proxy 怎么修改该默认行为, 都可以通过 Reflect 获取原生的默认行为;
1
2
3
4
5
6let proxy = new Proxy(target, {
set(target, name, value, receiver) {
let success = Reflect.set(target, name, value, receiver);
return success;
}
})
Reflect 对象的静态方法
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.has(obj, name)
Reflect.deleteProperty(obj, name)
Reflect.construct(target, args)
Reflect.getPrototypeOf(obj)
Reflect.setPrototypeOf(obj, newProto)
Reflect.apply(target, thisArg, args)
Reflect.defineProperty(target, propertyKey, attributes)
Reflect.getOwnPropertyDescriptor(target, propertyKey)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.ownKeys(target)
- Reflect.get(target, name, receiver)
查找并返回 target 对象 name 属性所对应的值, 如果没有该属性, 则返回 undefined;target: 目标对象, 若不是对象类型, 报错;
name: 对象键名 key;
receiver: 当 name 属性部署了 getter 时的 this 指向;
1 |
|
- Reflect.set(target, name, value, receiver)
设置target对象的name属性等于value; 若不存在 name 属性则先创建再赋值, 若存在则覆盖 name 属性值;target: 目标对象, 若不是对象类型, 报错;
name: 对象键名 key;
value: 期望设置的键值 value;
receiver: 当 name 属性部署了 setter 时的 this 指向;
1 |
|
- Reflect.has(obj, name)
查找 obj 对象内是否存在 name 属性, 若存在返回 true, 不存在返回 false; 等价于name in obj
的 in 运算符, 是命令行为向函数行为统一的体现;obj: 目标对象, 若不是对象类型, 报错;
name: 所要查找的属性名
1 |
|
- Reflect.deleteProperty(obj, name)
等同于delete obj[name]
,用于删除对象的属性; 返回一个布尔值。如果删除成功,或者被删除的属性不存在,返回true;删除失败,被删除的属性依然存在,返回false;obj: 目标对象, 若不是对象类型, 报错;
name: 所要删除的属性名
1 |
|
- Reflect.construct(target, args)
等同于new target(...args)
,提供了一种不使用 new 来调用构造函数的方法; 返回构造函数实例;target: 目标对象, 若不是对象类型, 报错;
args: 构造函数初始化参数;
1 |
|
Reflect.getPrototypeOf(obj)
obj: 目标对象, 若不是对象类型, 报错;
读取并返回对象的__proto__属性,对应Object.getPrototypeOf(obj)
;Reflect.getPrototypeOf
和Object.getPrototypeOf
的一个区别是: 如果参数不是对象,Object.getPrototypeOf
会将这个参数转为对象,然后再运行,而Reflect.getPrototypeOf
会报错。(体现了开头介绍的 Reflect 特性, 其修改了原先 Object 方法的一些不合理操作);1
2
3
4
5
6
7
8
9
10const obj = {
name: 'Siri',
age: 18,
}
let res = Reflect.getPrototypeOf(obj); // Object.prototype
// 区别
let msg1 = Object.getPrototypeOf(1); // [Number: 0]
let msg2 = Reflect.getPrototypeOf(1); // TypeError: Reflect.getPrototypeOf called on non-objectReflect.setPrototypeOf(obj, newProto)
设置目标对象的原型(prototype),对应Object.setPrototypeOf(obj, newProto)
方法。它返回一个布尔值,若成功则返回 true, 设置失败返回 false;Reflect.setPrototypeOf
与Object.setPrototypeOf
区别: 如果第一个参数不是对象,Object.setPrototypeOf
会返回第一个参数本身,而Reflect.setPrototypeOf
会报错; 如果第一个参数是 undefined 或 null,Object.setPrototypeOf
和Reflect.setPrototypeOf
都会报错;obj: 目标对象, 若不是对象类型, 报错;
newProto: 期望设置的原型;
1 |
|
- Reflect.apply(func, thisArg, args)
等同于Function.prototype.apply.call(func, thisArg, args)
,用于绑定 this 对象后执行回调函数。
一般来说,如果要绑定一个函数的this对象,用fn.apply(obj, args)
即可,但是如果函数定义了自己的 apply 方法,就只能写成Function.prototype.apply.call(fn, obj, args)
,而采用Reflect对象可以简化这种操作。func: 绑定 this 对象后触发的回调函数
thisArg: 期望绑定的 this 对象
args: 传递给 func 的函数参数
1 |
|
- Reflect.defineProperty(target, propertyKey, attributes)
等同于Object.defineProperty
,为对象定义属性, 若属性存在则覆盖原属性值, 返回一个布尔值。未来,后者会被逐渐废除,请从现在开始就使用Reflect.defineProperty
代替它;Reflect.defineProperty()
与Reflect.set()
使用场景区别:Reflect.defineProperty()
用于赋值和修改对象属性的属性描述(value, get, set, writable等),Reflect.set()
只能用于修改属性值(value);target: 目标对象, 若不是对象类型, 报错;
propertyKey: 需要赋值的对象属性;
attributes: 属性描述对象;
1 |
|
- Reflect.getOwnPropertyDescriptor(target, propertyKey)
等同于Object.getOwnPropertyDescriptor
,返回指定属性的描述对象,将来会替代掉后者;Reflect.getOwnPropertyDescriptor
和Object.getOwnPropertyDescriptor
的区别: 如果第一个参数不是对象,Object.getOwnPropertyDescriptor()
不报错,返回 undefined,而Reflect.getOwnPropertyDescriptor()
会抛出错误,表示参数非法;target: 目标对象, 若不是对象类型, 报错;
propertyKey: 属性键名;
1 |
|
- Reflect.isExtensible(target)
对应Object.isExtensible
,返回一个布尔值,表示当前对象是否可扩展; 与Object.isExtensible
区别: 如果参数不是对象,Object.isExtensible
会返回 false,因为非对象本来就是不可扩展的,而Reflect.isExtensible
会报错;target: 目标对象, 若不是对象类型, 报错;
1 |
|
- Reflect.preventExtensions(target)
对应Object.preventExtensions
方法,用于让一个对象变为不可扩展。返回一个布尔值,表示是否操作成功, 若操作成功则返回 true, 反之返回 false;
与Object.preventExtensions
的区别: 如果参数不是对象,Object.preventExtensions
在 ES5 环境报错,在 ES6 环境返回传入的参数,而Reflect.preventExtensions
会报错;target: 目标对象, 若不是对象类型, 报错;
1 |
|
- Reflect.ownKeys(target)
返回对象的所有属性(用数组包裹),基本等同于Object.getOwnPropertyNames
与Object.getOwnPropertySymbols
之和;target: 目标对象, 若不是对象类型, 报错;
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!