代理模式
代理模式
通过代理对象,我们可以更好地控制与某些对象的交互.例如当我们获取或者设置值时,每当我们与对象交互代理对象就可以确定该对象地行为.
一般来说,代理人是指代替他人的人.你无需直接与该人交谈,而是与代表您试图联系的人的代理人交谈. JavaScript 中也会发生同样的情况:我们将与 Proxy 对象交互,而不是直接与目标对象交互.
让我们创建一个person对象来代表John Doe
const person = {
name: 'John Doe',
age: 42,
nationality: 'American'
}
我们不想直接与该对象交互,而是希望与代理对象交互.在 JavaScript 中,我们可以通过创建 Proxy 的新实例来轻松创建新的代理.
const person = {
name: 'John Doe',
age: 42,
nationality: 'American'
}
const personProxy = new Proxy(person, {})
Proxy 的第二个参数是代表处理程序的对象。在处理程序对象中,我们可以根据交互类型定义特定的行为。尽管可以将许多方法添加到代理处理程序中,但最常见的两个是 get 和 set:
- get: 尝试访问属性时被调用
- set: 尝试设置属性时被调用
实际上最终会发生一下情况
我们将与 personProxy 交互,而不是直接与 person 对象交互。
让我们向 personProxy 代理添加处理程序,当尝试修改属性,从而调用代理上的 set 方法时,我们希望代理记录属性的先前值和新值。当尝试访问属性,从而调用代理上的 get 方法时,我们希望代理记录一个更易读的句子,其中包含属性的键和值。
const personProxy = new Proxy(person, {
get: (obj, prop) => {
console.log(`The value of ${prop} is ${obj[prop]}`);
},
set: (obj, prop, value) => {
console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
obj[prop] = value;
},
})
完美,让我们看看当我们尝试修改或检索属性时会发生什么.
当访问 name 属性时,Proxy 返回了一个听起来更好听的句子:The value of name is John Doe
修改年龄属性时,代理返回该属性的先前值和新值:将年龄从 42 更改为 43
代理对于添加验证很有用。用户不应该能够将人的年龄更改为字符串值,或给他们一个空名字。或者,如果用户尝试访问对象上不存在的属性,我们应该让用户知道。
让我们看看当我们尝试传递错误值时会发生什么!
代理确保我们不会用错误的值修改 person 对象,这有助于我们保持数据的纯净!
反射
JavaScript 提供了一个名为 Reflect 的内置对象,它使我们在使用代理时更容易操作目标对象。
以前,我们尝试通过直接获取或设置带有括号表示法的值来修改和访问代理内目标对象的属性。相反,我们可以使用 Reflect 对象。 Reflect 对象上的方法与处理程序对象上的方法具有相同的名称。
我们可以通过 Reflect.get() 和 Reflect.set() 访问或修改目标对象的属性,而不是通过 obj[prop] 访问属性或通过 obj[prop] = value 设置属性。这些方法接收与处理程序对象上的方法相同的参数。
const personProxy = new Proxy(person, {
get: (obj, prop) => {
console.log(`The value of ${prop} is ${Reflect.get(obj, prop)}`);
},
set: (obj, prop, value) => {
console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
Reflect.set(obj, prop, value);
},
});
完美,我们能通过Reflect对象轻易的修改和获取目标对象地值
权衡
代理是一种增强对对象行为的控制的强大方法。代理可以有各种用例:它可以帮助验证、格式化、通知或调试。
过度使用代理对象或对每个处理程序方法调用执行繁重的操作很容易对应用程序的性能产生负面影响。最好不要对性能关键型代码使用代理