第六章 JavaScript标准库 6.14 Reflect

112 阅读3分钟

6.14 Reflect

Reflect 对象与 Proxy 对象一样,也是 ES6 为了操作对象而提供的新 API。Reflect 对象的设计目的有这样几个。

  • (1) 将 Object 对象的一些方法移动到 Reflect 对象上。 在 ES5 中,Object 对象的许多方法是与语言本身相关的,而在 ES6 中,这些方法都被移动到 Reflect 对象上。例如,Object.defineProperty 方法可以用 Reflect.defineProperty 方法代替。
  • (2) 更合理的返回结果。 某些 Object 方法的返回结果可能不太合理,例如,Object.defineProperty 在无法定义属性时会抛出一个错误。但是在 Reflect.defineProperty 中,如果定义属性失败,它将返回 false。
  • (3) 将 Object 操作转换为函数操作。 某些 Object 操作是命令式的,例如 delete obj[name],而 Reflect.deleteProperty(obj, name)将其转换为函数形式。
  • (4) Reflect 方法与 Proxy 方法一一对应。 Reflect 对象的方法与 Proxy 对象的方法一一对应,这使得 Proxy 对象可以轻松调用相应的 Reflect 方法,并完成默认行为。这让我们在使用 Proxy 对象时能够更好地控制对象的行为,同时又可以使用 Reflect 对象来获取默认行为。例如,我们可以在 Proxy 对象中拦截对属性的读取,并使用 Reflect.get 方法获取默认行为。以下是一些使用 Reflect API 的示例: 1 使用 Reflect.get 获取对象属性的值:
const person = {
  name: 'Alice',
  age: 25,
};

const age = Reflect.get(person, 'age');
console.log(age); // 25

2 使用 Reflect.set 设置对象属性的值:

const person = {
  name: 'Alice',
  age: 25,
};

Reflect.set(person, 'age', 26);
console.log(person); // { name: 'Alice', age: 26 }

3 使用 Reflect.defineProperty 定义对象属性:

const person = {};
Reflect.defineProperty(person, 'name', {
  value: 'Alice',
  writable: false,
  configurable: false,
});

console.log(person.name); // 'Alice'

// 无法修改name属性的值,也无法删除该属性
person.name = 'Bob';
delete person.name;

console.log(person.name); // 'Alice'

像以上例子一样,Reflect 对象一共有 13 个静态方法,分别是: 1.Reflect.get(target, propertyKey, receiver):获取对象 target 中属性 propertyKey 的值,如果没有此属性,则返回 undefined。receiver 可选,作为 getter 函数的 this 值。 2.Reflect.set(target, propertyKey, value, receiver):设置对象 target 中属性 propertyKey 的值为 value,如果没有此属性,则创建该属性。receiver 可选,作为 setter 函数的 this 值。 3.Reflect.apply(target, thisArg, args):调用 target 函数,传入 thisArg 作为 this,args 作为参数列表。 4.Reflect.construct(target, args, newTarget):使用 args 参数列表作为构造函数 target 的参数,构造一个新的对象,并将 newTarget 作为其构造函数。 5.Reflect.defineProperty(target, propertyKey, attributes):定义对象 target 中属性 propertyKey 的特性(包括值、可写性、可枚举性、可配置性等)。 6.Reflect.deleteProperty(target, propertyKey):删除对象 target 中属性 propertyKey。 7.Reflect.has(target, propertyKey):判断对象 target 中是否有属性 propertyKey,返回布尔值。 8.Reflect.ownKeys(target):返回对象 target 自身属性名和 Symbol 类型的属性键组成的数组。 9.Reflect.isExtensible(target):判断对象 target 是否可扩展,返回布尔值。 10.Reflect.preventExtensions(target):使对象 target 不可扩展。 11.Reflect.getOwnPropertyDescriptor(target, propertyKey):获取对象 target 中属性 propertyKey 的描述符对象。 12.Reflect.getPrototypeOf(target):获取对象 target 的原型对象。 13.Reflect.setPrototypeOf(target, prototype):设置对象 target 的原型对象为 prototype。 值得注意的是,Reflect 与 Object 方法的区别在于,Reflect 方法会返回一个 Boolean 类型或者抛出一个错误异常,而 Object 方法只返回一个 Boolean 类型。 可以以 Object.defineProperty 和 Reflect.defineProperty 方法为例来说明。 Object.defineProperty 方法用于定义一个对象的属性,当属性无法被定义时,该方法会抛出一个错误异常: const obj = {}; Object.defineProperty(obj, 'foo', { value: 'bar', writable: false, configurable: false }); // 此时再尝试修改 foo 的值或删除 foo 属性,就会抛出错误异常 而使用 Reflect.defineProperty 方法来定义属性时,如果属性无法被定义,则该方法会返回 false: const obj = {}; const success = Reflect.defineProperty(obj, 'foo', { value: 'bar', writable: false, configurable: false }); if (success) { console.log('foo 属性定义成功'); } else { console.log('foo 属性定义失败'); } 因此,使用 Reflect 方法进行对象操作时,可以更精确地获取操作结果,从而更好地处理错误情况。