携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
语法结构
const proxy = new Proxy(target, handler);
target: 要使用Proxy包装的目标对象,可以是任何类型的对象,包括原生数组,函数,甚至另一个代理。handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理proxy的行为。
名词描述
Proxy 用于修改某些操作的默认行为,也可以理解为在目标对象之前增设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。这个词的原理为代理,在这里可以表示由它来代理某些操作,译为代理器:
var target = {label: '演员'};
var proxy = new Proxy(target, {
set: function(target, key, value, receiver){
return Reflect.set(target, key, '我是' + value, receiver);
},
get: function(target, key, receiver){
return target[key];
}
});
proxy.label = '峡谷演员'; // 触发set:'我是' + value
console.log(target); // 触发set: {label: '我是峡谷演员'}
Object.defineProperty 是用于监听属性,而 Proxy 是监听整个对象,通过调用 new Proxy() ,可以创建一个代理用来替代另一个对象被称为目标,这个代理对目标对象进行了虚拟,因此该代理与该目标对象表面上可以被当作同一个对象来对待。代理允许拦截在目标对象上的底层操作,而这原本是JavaScript引擎的内部能力,拦截行为使用了一个能够响应特定操作的函数,即通过Proxy去对一个对象进行代理之后,我们将得到一个和被代理对象几乎完全一样的对象,并且可以从底层实现对这个对象进行完全的监控。
下面我们通过一道常见的面试题(实现 a===1&&a===2&&a===3 为true),来看看 Object.defineProperty 和 Proxy 代理的简单运用:
// Object.defineProperty 定义的是属性
// 可以实现对于题目的要求
var _d = 0;
Object.defineProperty(window, "a", {
get:function(){
return ++_d;
}
})
console.log(a===1 && a===2 && a===3); // true
// proxy 代理的是对象
// 因此在调用时实际与题目要求并不太相符
// 但同样也是一种实现方式
var _p = 0;
var proxy = new Proxy(window, {
set: function(target, key, value, receiver){
return Reflect.set(target, key, value, receiver);
},
get: function(target, key, receiver){
if(key === "a") return ++_p;
else return window[key];
}
});
console.log(proxy.a===1 && proxy.a===2 && proxy.a===3); // true