Proxy 和 Reflect

Proxy

作用

可以通过 Proxy 来代理对象,然后定制该对象的基本操作(如属性查找、赋值、枚举、函数调用等)。

语法

1
const p = new Proxy(target, handler)

参数:

  • target:被代理的对象,可以是任何类型的对象,包括原生数组,函数,甚至另一个代理。

  • handler:以函数为属性值的对象,key 为操作名称,value 为自定义实现。

    • 支持的 key:

      • get:function(target, property, receiver) {//…}
        • 属性读取操作的捕捉器。
      • set(target, prop,value, receiver) {//…}
        • 属性设置操作的捕捉器。
      • has(target, prop) {//…}
        • in 操作符的捕捉器。
      • deleteProperty(target, prop) {//…}
        • delete 操作符的捕捉器。
      • getPrototypeOf(target) { //…}
        • Object.getPrototypeOf 方法的捕捉器。
      • setPrototypeOf(target, newProto) {//…}
        • Object.setPrototypeOf 方法的捕捉器。
      • isExtensible(target) {//…}
        • Object.isExtensible方法的捕捉器。
      • preventExtensions(target) {//…}
        • Object.preventExtensions方法的捕捉器。
      • getOwnPropertyDescriptor(target, prop) {//…}
        • Object.getOwnPropertyDescriptor 方法的捕捉器。
        • defineProperty(target, prop, descriptor ) {//…}
          • Object.defineProperty方法的捕捉器。
        • ownKeys(target) {//…}
          • Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。
        • apply(target, thisArg, argumentsList) {//…}
          • 函数调用操作的捕捉器。
        • construct(target, args) {//…}
          • new 操作符的捕捉器。

示例

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
30
31
let validator = {
set: function(obj, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('The age is not an integer');
}
if (value > 200) {
throw new RangeError('The age seems invalid');
}
}

// The default behavior to store the value
obj[prop] = value;

// 表示成功
return true;
}
};

let person = new Proxy({}, validator);

person.age = 100;

console.log(person.age);
// 100

person.age = 'young';
// 抛出异常: Uncaught TypeError: The age is not an integer

person.age = 300;
// 抛出异常: Uncaught RangeError: The age seems invalid

Reflect

可以把 Reflect 当做 Object 的升级版,但没有构造函数,不能使用 new 操作符。

Reflect 所有的属性和方法都是静态的,所有的方法名和 Proxy handle 提供的方法名一致。

作用

  • 可以和 Object 一样操作对象。

  • 修改 Object 操作的一些返回值,

  • 让 Object 的操作变成函数行为

  • Reflect 和 Proxy 的方法一一对应,Proxy 对象可使用 Reflect 完成默认操作的调用

示例

1
2
3
4
5
6
7
8
9
10
11
12
const duck = {
name: 'Maurice',
color: 'white',
greeting: function() {
console.log(`Quaaaack! My name is ${this.name}`);
}
}

Reflect.has(duck, 'color');
// true
Reflect.has(duck, 'haircut');
// false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Object
var obj = {};
Reflect.set(obj, "prop", "value"); // true
obj.prop; // "value"

// Array
var arr = ["duck", "duck", "duck"];
Reflect.set(arr, 2, "goose"); // true
arr[2]; // "goose"

// It can truncate an array.
Reflect.set(arr, "length", 1); // true
arr; // ["duck"];

// With just one argument, propertyKey and value are "undefined".
var obj = {};
Reflect.set(obj); // true
Reflect.getOwnPropertyDescriptor(obj, "undefined");
// { value: undefined, writable: true, enumerable: true, configurable: true }