Technology Sharing

ES6 Reflect Detailed Explanation (Part 3)

2024-07-12

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

The Reflect object, like the Proxy object, is also a new API provided by ES6 for operating objects. The Reflect object is designed for four purposes.

  1. Put some methods of the Object object that are obviously internal to the language (such as Object.defineProperty) on the Reflect object. At this stage, some methods are deployed on both the Object and Reflect objects, and new methods in the future will only be deployed on the Reflect object. In other words, the internal methods of the language can be obtained from the Reflect object.
  2. Modify the return results of some Object methods to make them more reasonable. For example, Object.defineProperty(obj, name, desc) will throw an error when the property cannot be defined, while Reflect.defineProperty(obj, name, desc) will return 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. Make Object operations become function behaviors. Some Object operations are imperative, such as name in obj and delete obj[name], and Reflect.has(obj, name) and Reflect.deleteProperty(obj, name) make them function behaviors.
// 老写法
'assign' in Object // true
// 新写法
Reflect.has(Object, 'assign') // true
  • 1
  • 2
  • 3
  • 4
  1. The methods of the Reflect object correspond one-to-one with the methods of the Proxy object. As long as it is a method of the Proxy object, you can find the corresponding method on the Reflect object. This allows the Proxy object to easily call the corresponding Reflect method to complete the default behavior as the basis for modifying the behavior. In other words, no matter how the Proxy modifies the default behavior, you can always get the default behavior on 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

The Proxy method intercepts the property assignment behavior of the target object. It uses the Reflect.set method to assign values ​​to the object's properties, ensuring that the original behavior is completed, and then deploys additional functionality.

Common methods:

Reflect.get(target, propertyKey[, receiver]): Get the property of an object.
Reflect.set(target, propertyKey, value[, receiver]): Sets the property of an object.
Reflect.has(target, propertyKey): Determines whether the property exists on the object.
Reflect.deleteProperty(target, propertyKey): Deletes a property of an object.
Reflect.ownKeys(target): Returns an array of all the properties of the object itself.
Reflect.getOwnPropertyDescriptor(target, propertyKey): Get the descriptor of an object property.
Reflect.defineProperty(target, propertyKey, attributes): Define or modify the properties of an object.
Reflect.preventExtensions(target): Prevents the object from being extended.
Reflect.isExtensible(target): Determines whether the object is extensible.
Reflect.getExtension(target): Get the prototype of the object.
Reflect.setPrototypeOf(target, prototype): Sets the prototype of an object.

Example 1: Using 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

Example 2: Using 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

Example 3: Using Reflect.has

let obj = { name: "Alice" };

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

Example 4: Using 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

Example 5: Using Reflect.ownKeys

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

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

Example 6: Using 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

Example 7: Using Reflect.isExtensible

let obj = { name: "Alice" };

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

Example 8: Using Reflect.getPrototypeOf and 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

The Reflect object provides a set of methods corresponding to the Proxy trap, making intercepting JavaScript operations more intuitive and convenient. Using Reflect can ensure the consistency and expected behavior of operations, especially when failures or errors need to be clearly captured.