# JavaScript—Proxy| 青训营笔记

86 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天

Proxy

Proxy是JavaScript的一个新特性,它可以创建一个代理对象,这个代理对象可以拦截对目标对象的操作,例如属性的读取、赋值、方法的调用等等。代理对象和目标对象可以有完全不同的行为,代理对象可以在目标对象的基础上添加一些额外的逻辑和约束,从而使得目标对象更加安全、可控和可维护。

创建Proxy对

要创建一个代理对象,我们需要使用JavaScript的内置Proxy构造函数。该构造函数接受两个参数:一个目标对象和一个处理程序对象。目标对象是我们想要拦截的对象,处理程序对象定义了我们要如何拦截目标对象的操作。下面是一个简单的例子:

const target = { name: '张三' };
const handler = {
  get: function(target, prop, receiver) {
    console.log(`读取 ${prop} 属性`);
    return target[prop];
  },
  set: function(target, prop, value, receiver) {
    console.log(`设置 ${prop} 属性为 ${value}`);
    target[prop] = value;
  }
};

const proxy = new Proxy(target, handler)

在上面的例子中,我们创建了一个目标对象**target ,它有一个name属性,我们还创建了一个处理程序对象handler ,它包含了两个拦截器函数: getset 。然后,我们使用Proxy构造函数来创建一个代理对象proxy ,它将目标对象target和处理程序对象handler**关联在一起。现在,我们可以对代理对象进行操作,并且可以看到我们定义的拦截器函数被调用了。

Proxy的拦截器

Proxy对象支持多种拦截器,例如:get、set、has、apply等。这些拦截器函数可以在目标对象被访问或者修改的时候被自动调用。拦截器函数接受一些参数,包括:目标对象、属性名、接收器等等。下面是一个例子:

const target = { name: '张三' };
const handler = {
  get: function(target, prop, receiver) {
    console.log(`读取 ${prop} 属性`);
    return target[prop];
  },
  set: function(target, prop, value, receiver) {
    console.log(`设置 ${prop} 属性为 ${value}`);
    target[prop] = value;
  }
};
const proxy = new Proxy(target, handler);

console.log(proxy.name);
proxy.age = 20;

在上面的例子中,我们定义了**getset两个拦截器函数。当我们读取代理对象的name属性时,拦截器函数get被调用,并输出了日志信息。当我们给代理对象设置age属性时,拦截器函数set**被调用,并输出了日志信息。这个例子演示了Proxy的拦截器函数的基本用法,我们可以通过拦截器函数来修改目标对象的行为。

除了get和set,还有一些其他的拦截器函数,例如:has、apply、construct等等。下面是一个has拦截器的例子:

const target = { name: '张三' };
const handler = {
  has: function(target, prop) {
    console.log(`判断 ${prop} 属性是否存在`);
    return prop in target;
  }
};
const proxy = new Proxy(target, handler);

console.log('name' in proxy);
console.log('age' in proxy);

在上面的例子中,我们定义了个has拦截器函数,当我们使用**in运算符判断代理对象的属性是否存在时,这个拦截器函数被调用,并输出了日志信息。在这个例子中,我们使用了in运算符来判断属性是否存在,但是我们也可以使用其他方法,例如: Reflect.has 。下面是一个使用Reflect.has**的例子:

const target = { name: '张三' };
const handler = {
  has: function(target, prop) {
    console.log(`判断 ${prop} 属性是否存在`);
    return Reflect.has(target, prop);
  }
};
const proxy = new Proxy(target, handler);

console.log('name' in proxy);
console.log('age' in proxy);

在上面的例子中,我们使用了**Reflect.has方法来判断属性是否存在,这个方法的行为和in**运算符是一样的。

Proxy的最佳实践

在使用Proxy时,我们应该遵循一些最佳实践,以确保我们的代码具有可读性、可维护性和可扩展性。下面是一些最佳实践:

  1. 只拦截必要的操作:不要对所有操作都进行拦截,这会导致代码变得混乱不堪。只对需要进行拦截的操作进行拦截。
  2. 拦截器函数要保持简洁明了:拦截器函数应该尽可能地保持清晰明了,不要在拦截器函数中进行复杂的逻辑处理。
  3. 尽量使用Reflect:使用Reflect可以使代码更加简洁和易读。例如:使用**Reflect.get来替代target[prop] ,使用Reflect.set来替代target[prop] = value**。
  4. 将代理对象和目标对象分开:不要将代理对象和目标对象混在一起,这会导致代码难以理解和维护。应该将代理对象和目标对象分开,并在代码中使用有意义的变量名。