Proxy

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

术语

handler

包含捕捉器(trap)的占位符对象,可译为处理器对象。

traps

提供属性访问的方法。这类似于操作系统中捕获器的概念。

target

被 Proxy 代理虚拟化的对象。它常被作为代理的存储后端。根据目标验证关于对象不可扩展性或不可配置属性的不变量(保持不变的语义)。

语法

1
const p = new Proxy(target, handler)

参数

target

要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

handler

一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。

方法

handler.apply()

1
2
3
4
var p = new Proxy(target, {
apply: function(target, thisArg, argumentsList) {
}
});

描述

handler.apply 方法用于拦截函数的调用。

参数

以下是传递给apply方法的参数,this上下文绑定在handler对象上.

  • target

    目标对象(函数)。

  • thisArg

    被调用时的上下文对象。

  • argumentsList

    被调用时的参数数组。

返回值

apply方法可以返回任何值。

示例

1
2
3
4
5
6
7
8
var p = new Proxy(function() {}, {
apply: function(target, thisArg, argumentsList) {
console.log('called: ' + argumentsList.join(', '));
return argumentsList[0] + argumentsList[1] + argumentsList[2];
}
});

console.log(p(1, 2, 3)); // 6

handler.construct()

1
2
3
4
var p = new Proxy(target, {
construct: function(target, argumentsList, newTarget) {
}
});

描述

handler.construct() 方法用于拦截 new操作符。

参数

下面的参数将会传递给construct方法,this绑定在handler上。

  • target

    目标对象。

  • argumentsList

    constructor的参数列表。

  • newTarget

    最初被调用的构造函数,就上面的例子而言是p。

返回值

construct 方法必须返回一个对象。

示例

1
2
3
4
5
6
7
8
var p = new Proxy(function() {}, {
construct: function(target, argumentsList, newTarget) {
console.log('called: ' + argumentsList.join(', '));
return { value: argumentsList[0] * 10 };
}
});

console.log(new p(1).value); // 10

handler.defineProperty()

1
2
3
4
var p = new Proxy(target, {
defineProperty: function(target, property, descriptor) {
}
});

描述

handler.defineProperty() 用于拦截对对象的 Object.defineProperty() 操作。

参数

下列参数将会被传递给 defineProperty 方法。 this 绑定在 handler 对象上。

  • target

    目标对象。

  • property

    待检索其描述的属性名。

  • descriptor

    待定义或修改的属性的描述符。

返回值

defineProperty 方法必须以一个 Boolean 返回,表示定义该属性的操作成功与否。

示例

以下代码演示如何拦截对目标对象的 Object.defineProperty() 操作。

1
2
3
4
5
6
7
8
9
var p = new Proxy({}, {
defineProperty: function(target, prop, descriptor) {
console.log('called: ' + prop);
return true;
}
});

var desc = { configurable: true, enumerable: true, value: 10 };
Object.defineProperty(p, 'a', desc); // "called: a"

handler.deleteProperty()

1
2
3
4
var p = new Proxy(target, {
deleteProperty: function(target, property) {
}
});

描述

handler.deleteProperty() 方法可以拦截 delete 操作。

参数

deleteProperty 方法将会接受以下参数。 this 被绑定在 handler上。

  • target

    目标对象。

  • property

    待删除的属性名。

返回值

deleteProperty 必须返回一个 Boolean 类型的值,表示了该属性是否被成功删除。

示例

1
2
3
4
5
6
7
8
var p = new Proxy({}, {
deleteProperty: function(target, prop) {
console.log('called: ' + prop);
return true;
}
});

delete p.a; // "called: a"

handler.get()

1
2
3
4
var p = new Proxy(target, {
get: function(target, property, receiver) {
}
});

描述

handler.get 方法用于拦截对象的读取属性操作。

参数

以下是传递给get方法的参数,this上下文绑定在handler对象上.

  • target

    目标对象。

  • property

    被获取的属性名。

  • receiver

    Proxy或者继承Proxy的对象

返回值

get方法可以返回任何值。

示例

1
2
3
4
5
6
7
8
var p = new Proxy({}, {
get: function(target, prop, receiver) {
console.log("called: " + prop);
return 10;
}
});

console.log(p.a); // 10

handler.set()

1
2
3
4
const p = new Proxy(target, {
set: function(target, property, value, receiver) {
}
});

描述

handler.set() 方法用于拦截设置属性值的操作。

参数

以下是传递给 set() 方法的参数。this 绑定在 handler 对象上。

  • target

    目标对象。

  • property

    将被设置的属性名或 Symbol

  • value

    新属性值。

  • receiver

    最初被调用的对象。通常是 proxy 本身,但 handler 的 set 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。

返回值

set() 方法应当返回一个布尔值。

  • 返回 true 代表属性设置成功。
  • 在严格模式下,如果 set() 方法返回 false,那么会抛出一个 TypeError 异常。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
var p = new Proxy({}, {
set: function(target, prop, value, receiver) {
target[prop] = value;
console.log('property set: ' + prop + ' = ' + value);
return true;
}
})

console.log('a' in p); // false

p.a = 10; // "property set: a = 10"
console.log('a' in p); // true
console.log(p.a); // 10

handler.has()

1
2
3
4
var p = new Proxy(target, {
has: function(target, prop) {
}
});

描述

handler.has 方法可以看作是针对 in 操作的钩子。

参数

下面是传递给 has 方法的参数. this is bound to the handler.

  • target

    目标对象.

  • prop

    需要检查是否存在的属性.

返回值

has 方法返回一个boolean属性的值。

示例

1
2
3
4
5
6
7
8
var p = new Proxy({}, {
has: function(target, prop) {
console.log('called: ' + prop);
return true;
}
});

console.log('a' in p); // true