JavaScript 中的代理 Proxy

158 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

代理 proxy

ECMAScript 6 中新增代理和反射的特性。即给目标对象定义一个关联的代理对象,而这个代理对象可以作为抽象的目标对象来使用。代理对象作用就是,在操作目标对象时对目标对象的影响之前,在代理对象中对这些操作进行控制。

代理是目标对象的抽象。有点像指针,可以是目标对象的替身,又独立于目标对象。可以直接对目标对象进行操作,也可以通过代理来操作。

创建代理

使用 Proxy 构造函数创建的。。这个构造函数接收两个参数:目标对象和处理程序对象

const target = {
  id: "target"
}
​
const handler = {}
​
const proxy = new Proxy(target, handler);

Target 是目标对象,handler 是处理程序对象,proxy 就是那个代理对象,只要在代理对象上执行的任何操作实际上都会应用到目标对象。

比如,访问同一个属性时,值时同一个

console.log(target.id); // 输出结果: target 
console.log(proxy.id); //  输出结果: target

给目标对象的属性赋值就对作用到目标对象和代理对象上,同样如果给代理对象的属性赋值也是会作用到目标对象和代理对象上。

target.id = 'Tom'; 
console.log(target.id); // 输出结果:Tom 
console.log(proxy.id); // 输出结果:Tom proxy.id = 'Jerry'; 
console.log(target.id); // 输出结果:Jerry 
console.log(proxy.id); //  输出结果:Jerry 

使用对象的 hasOwnProperty() 方法,目标对象和代理对象使用时都是作用到目标对象

console.log(target.hasOwnProperty('id')); // 输出结果:true 
console.log(proxy.hasOwnProperty('id')); //  输出结果:true

但需要注意,proxy.prototype 是 undefined ,所以如果使用 instanceof 操作时就会报错TypeError: Function has non-object prototype

代理作用:捕获器(拦截器)

创建代理时,还有一个参数是处理程序对象。处理程序对象中是定义零个或多个的捕获器,这些捕获器都是对应到对对象操作的捕获器。就是在一些操作作用到目标对象之前,先调用处理程序对象中的捕获器,再执行操作。

比如,在处理程序对象中定义一个 get 操作的捕获器,这样在获取数据时就会触发捕获器。

const target = {
  name:" Tom"
}
​
// 处理程序对象中定一个对get操作的拦截
const handler ={
  get() {
    return 'handler override'
  }
}
​
// 创建 代理
const proxy = new Proxy(target, handler);
​
console.log(target.name); // Tom 
console.log(proxy.name); // handler override

在对目标对象获取name时,直接输出结果,但是在代理对象使用时,就会触发 handler 中定义get()方法。这是因为所有的操作只要发生在代理对象上就会触发 get 捕获器,在目标对象上执行操作时不会触发。

处理程序对象 handler 的捕获器可以接收到三个参数

const handler ={
  get(trapTarget, property, receiver) {
    return 'handler override'
  }
}
  • trapTarget 目标对象
  • property 要查询的参数
  • receiver 代理对象

每个捕获器都有自己的参数,然后可以基于自己的参数重建原始操作。