Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
语法
const p = new Proxy(target, handler)
参数:
target 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。 handler 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
方法:
Proxy.revocable() 创建一个可撤销的Proxy对象。
handler 对象的方法
handler.getPrototypeOf() Object.getPrototypeOf 方法的捕捉器。
handler.setPrototypeOf() Object.setPrototypeOf 方法的捕捉器。
handler.isExtensible() Object.isExtensible 方法的捕捉器。
handler.preventExtensions() Object.preventExtensions 方法的捕捉器。
handler.getOwnPropertyDescriptor() Object.getOwnPropertyDescriptor 方法的捕捉器。
handler.defineProperty() Object.defineProperty 方法的捕捉器。
handler.has() in 操作符的捕捉器。
handler.get() 属性读取操作的捕捉器。
handler.set() 属性设置操作的捕捉器。
handler.deleteProperty() delete 操作符的捕捉器。
handler.ownKeys() Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。
handler.apply() 函数调用操作的捕捉器。
handler.construct() new 操作符的捕捉器
示例
const handler = {
get: function(obj, prop) {
return prop in obj ? obj[prop] : 37;
}
};
const p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37
无操作转发代理 在以下例子中,我们使用了一个原生 JavaScript 对象,代理会将所有应用到它的操作转发到这个对象上。
let target = {};
let p = new Proxy(target, {});
p.a = 37; // 操作转发到目标
console.log(target.a); // 37. 操作已经被正确地转发
验证 通过代理,你可以轻松地验证向一个对象的传值。下面的代码借此展示了 set handler 的作用。
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
方法代理可以轻松地通过一个新构造函数来扩展一个已有的构造函数。这个例子使用了construct和apply。
function extend(sup, base) {
var descriptor = Object.getOwnPropertyDescriptor(
base.prototype, "constructor"
);
base.prototype = Object.create(sup.prototype);
var handler = {
construct: function(target, args) {
var obj = Object.create(base.prototype);
this.apply(target, obj, args);
return obj;
},
apply: function(target, that, args) {
sup.apply(that, args);
base.apply(that, args);
}
};
var proxy = new Proxy(base, handler);
descriptor.value = proxy;
Object.defineProperty(base.prototype, "constructor", descriptor);
return proxy;
}
var Person = function (name) {
this.name = name
};
var Boy = extend(Person, function (name, age) {
this.age = age;
});
Boy.prototype.sex = "M";
var Peter = new Boy("Peter", 13);
console.log(Peter.sex); // "M"
console.log(Peter.name); // "Peter"
console.log(Peter.age); // 13