技術共有

ES6リフレクト詳細解説(3)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Reflect オブジェクトは、Proxy オブジェクトと同様に、ES6 が提供するオブジェクトを操作するための新しい API です。 Reflect オブジェクトは 4 つの目的のために設計されています。

  1. 明らかに言語の内部にある Object オブジェクトのメソッド (Object.defineProperty など) を Reflect オブジェクトに配置します。この段階では、一部のメソッドは Object オブジェクトと Reflect オブジェクトの両方にデプロイされますが、将来の新しいメソッドは Reflect オブジェクトにのみデプロイされます。つまり、言語の内部メソッドは Reflect オブジェクトから取得できます。
  2. 一部の Object メソッドの戻り結果を変更して、より合理的なものにします。たとえば、Object.defineProperty(obj, name, desc) はプロパティを定義できない場合にエラーをスローしますが、Reflect.defineProperty(obj, name, desc) は false を返します。
// 老写法
try {
  Object.defineProperty(target, property, attributes);
  // success
} catch (e) {
  // failure
}
// 新写法
if (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // failure
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  1. オブジェクトの操作を機能的な動作にしましょう。 name in obj や delete obj[name] など、一部のオブジェクト操作は必須ですが、Reflect.has(obj, name) と Reflect.deleteProperty(obj, name) はそれらを関数的な動作に変換します。
// 老写法
'assign' in Object // true
// 新写法
Reflect.has(Object, 'assign') // true
  • 1
  • 2
  • 3
  • 4
  1. Reflect オブジェクトのメソッドと Proxy オブジェクトのメソッドは 1 対 1 に対応しており、Proxy オブジェクトのメソッドである限り、対応するメソッドは Reflect オブジェクト上に存在します。これにより、Proxy オブジェクトは対応する Reflect メソッドを簡単に呼び出してデフォルトの動作を完了し、動作を変更するための基礎として機能することができます。言い換えれば、Proxy がデフォルトの動作をどのように変更しても、Reflect では常にデフォルトの動作を取得できます。
Proxy(target, {
  set: function(target, name, value, receiver) {
    var success = Reflect.set(target, name, value, receiver);
    if (success) {
      console.log('property ' + name + ' on ' + target + ' set to ' + value);
    }
    return success;
  }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Proxy メソッドは、ターゲット オブジェクトの属性割り当て動作をインターセプトします。 Reflect.set メソッドを使用してオブジェクトのプロパティに値を割り当て、元の動作が完了していることを確認してから、追加の機能をデプロイします。

一般的に使用される方法:

Reflect.get(target, propertyKey[,receiver]): オブジェクトのプロパティを取得します。
Reflect.set(target, propertyKey, value[,receiver]): オブジェクトのプロパティを設定します。
Reflect.has(target, propertyKey): プロパティがオブジェクトに存在するかどうかを判断します。
Reflect.deleteProperty(target, propertyKey): オブジェクトのプロパティを削除します。
Reflect.ownKeys(target): オブジェクト自体のすべてのプロパティの配列を返します。
Reflect.getOwnPropertyDescriptor(target, propertyKey): オブジェクト プロパティの記述子を取得します。
Reflect.defineProperty(target, propertyKey,attributes): オブジェクトのプロパティを定義または変更します。
Reflect.preventExtensions(target): オブジェクトが拡張されないようにします。
Reflect.isExtensible(target): オブジェクトが拡張可能かどうかを判断します。
Reflect.getExtension(target): オブジェクトのプロトタイプを取得します。
Reflect.setPrototypeOf(target,prototype): オブジェクトのプロトタイプを設定します。

例 1: Reflect.get の使用

let obj = { name: "Alice", age: 25 };
let propName = "name";

console.log(Reflect.get(obj, propName)); // 输出:Alice
console.log(Reflect.get(obj, "gender")); // 输出:undefined
  • 1
  • 2
  • 3
  • 4
  • 5

例 2: Reflect.set の使用

let obj = { name: "Alice" };

// 设置属性
console.log(Reflect.set(obj, "age", 30)); // 输出:true

console.log(obj); // 输出:{ name: "Alice", age: 30 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

例 3: Reflect.has の使用

let obj = { name: "Alice" };

console.log(Reflect.has(obj, "name")); // 输出:true
console.log(Reflect.has(obj, "age"));  // 输出:false
  • 1
  • 2
  • 3
  • 4

例 4: Reflect.deleteProperty の使用

let obj = { name: "Alice", age: 30 };

// 删除属性
console.log(Reflect.deleteProperty(obj, "age")); // 输出:true

console.log(obj); // 输出:{ name: "Alice" }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

例 5: Reflect.ownKeys の使用

let obj = { name: "Alice", age: 30 };

console.log(Reflect.ownKeys(obj)); // 输出:["name", "age"]
  • 1
  • 2
  • 3

例 6: Reflect.preventExtensions の使用

let obj = { name: "Alice" };

// 防止对象被扩展
console.log(Reflect.preventExtensions(obj)); // 输出:true

// 尝试添加新属性
console.log(Reflect.set(obj, "age", 30)); // 输出:false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

例 7: Reflect.isExtensible の使用

let obj = { name: "Alice" };

console.log(Reflect.isExtensible(obj)); // 输出:true
  • 1
  • 2
  • 3

例 8: Reflect.getPrototypeOf と Reflect.setPrototypeOf の使用

let proto = { sayHello: function() { console.log("Hello!"); }};
let obj = Object.create(proto);

console.log(Reflect.getPrototypeOf(obj) === proto); // 输出:true

// 设置新原型
let newProto = { sayGoodbye: function() { console.log("Goodbye!"); }};
Reflect.setPrototypeOf(obj, newProto);

console.log(obj.sayGoodbye); // 可以访问新原型上的方法
obj.sayGoodbye(); // 输出:Goodbye!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Reflect オブジェクトは、プロキシ トラップに対応する一連のメソッドを提供し、JavaScript 操作のインターセプトをより直観的かつ便利にします。 Reflect を使用すると、特に障害状態やエラーを明示的にキャプチャする必要がある場合に、操作の一貫性と期待される動作が保証されます。