Reflect

Reflect 对象简介

用Object的语法会做一些额外的事情,不直接。

而引入了Reflect就可以通过Reflect来直接调用对象的 内部方法

Reflect 是 ES6 (ECMAScript 2015) 中新增的一个内置对象,它提供了一些方法来处理对象属性的查询和操作。Reflect 对象的方法与 Object 对象的方法相似,但有一些关键的区别:

  • Reflect 的方法不会改变 this 的指向,而 Object 方法会。
  • Reflect 的方法都是静态的不能被继承或作为对象的方法调用
  • Reflect 的方法在操作失败时不会抛出异常,而是返回 false undefined

Reflect 的主要方法

receiver可以用来指定this

  1. Reflect.get(target, propertyKey, receiver)

    • 获取对象 target 上的属性 propertyKey 的值。
    • 如果属性不存在或不可访问,返回 undefined
  2. Reflect.set(target, propertyKey, value, receiver)

    • 设置对象 target 上的属性 propertyKey 的值为 value
    • 如果操作失败(如属性是不可写的),返回 false
  3. Reflect.has(target, propertyKey)

    • 检查对象 target 是否有属性 propertyKey
    • 返回 truefalse
  4. Reflect.deleteProperty(target, propertyKey)

    • 删除对象 target 上的属性 propertyKey
    • 如果删除成功,返回 true;如果属性是不可配置的,则返回 false
  5. Reflect.ownKeys(target)

    • 返回对象 target 的所有自有属性的键名,包括 Symbol 类型的键名。
  6. Reflect.getOwnPropertyDescriptor(target, propertyKey)

    • 返回对象 target 上属性 propertyKey 的描述符。
    • 如果属性不存在,返回 undefined
  7. Reflect.defineProperty(target, propertyKey, attributes)

    • 定义或修改对象 target 上属性 propertyKey 的描述符。
    • 如果操作失败(如属性是不可配置的),抛出异常。
  8. Reflect.preventExtensions(target)

    • 阻止对象 target 被扩展。
    • 如果对象已经被阻止扩展,返回 true;否则返回 false
  9. Reflect.isExtensible(target)

    • 检查对象 target 是否可以被扩展。
    • 返回 truefalse
  10. Reflect.getOwnPropertyDescriptors(target)

    • 返回对象 target 的所有自有属性的描述符。
  11. Reflect.apply(target, thisArgument, argumentsList)

    • 调用 target 函数,将 this 绑定到 thisArgument 上,并传入 argumentsList 作为参数数组。
  12. Reflect.construct(target, argumentsList, newTarget)

    • 使用 target 构造函数创建一个新对象,传入 argumentsList 作为参数数组。
    • 如果提供了 newTarget,则使用 newTarget 作为构造函数的原型。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const obj = { x: 1, y: 2 };

// 使用 Reflect.get 获取属性
const x = Reflect.get(obj, 'x'); // x => 1

// 使用 Reflect.set 设置属性
const success = Reflect.set(obj, 'z', 3); // success => true
console.log(obj.z); // 3

// 使用 Reflect.has 检查属性
const hasY = Reflect.has(obj, 'y'); // hasY => true

// 使用 Reflect.deleteProperty 删除属性
const deleted = Reflect.deleteProperty(obj, 'x'); // deleted => true
console.log(obj.x); // undefined

Proxy和Reflect的配合使用

为什么Proxy一定要配合Reflect使用?恰恰是为了触发代理对象的劫持时保证正确的 this 上下文指向

针对于 get 陷阱(当然 set 其他之类涉及到 receiver 的陷阱同理):

  • Proxy 中接受的 Receiver 形参表示 代理对象本身或者继承与代理对象的对象
  • Reflect 中传递的 Receiver 实参表示 修改执行原始操作时的 this 指向。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const obj = {
a: 1,
b: 2,
// 定义一个 getter 属性 c,计算 a 和 b 的和
get c() {
return this.a + this.b;
}
};

// 创建一个 Proxy 对象,用于拦截对 obj 的访问
const proxy = new Proxy(obj, {
// 当访问 obj 的属性时触发 get 操作
get(target, key) {
console.log('正在访问:', key);
// return target[key];
// 当直接返回 target[key] 时,此时的this就指向target,只输出正在访问的属性名称和最终的值
// 正在访问: c
// 3
return Reflect.get(obj, key, proxy);
// 如果使用 Reflect.get 方法,此时把this的值绑定到proxy上,则会输出所有访问路径上的属性名
// 正在访问: c
// 正在访问: a
// 正在访问: b
// 3
}
});

// 访问 proxy 对象的属性 c,触发了拦截器中的 get 操作
console.log(proxy.c);