Skip to content

代理模式

发布于: at 08:00

拦截并控制目标对象的交互

使用Proxy对象,我们可以使用多一层交互来控制对象。一个代理对象可以确定我们操作一个对象的行为,比如说获取一个值或者设定一个值


简单的来说,代理模式就不是直接对一个人说话了,而是另外又找了一个人做传话的。在Javascript中,我们不与对象直接交互,而是通过Proxy对象与目标的对象交互。


如何使用

怎么写呢,这边举个例子

const person = {
  name: "max",
  age: 21,
};
const personProxy = new Proxy(person, {
  get(obj, prop) {
    console.log(obj[prop]);
    return obj[prop];
  },
  set(obj, prop, value) {
    obj[prop] = value;
    console.log(obj[prop]);
  },
});
personProxy.name;
personProxy.age = 22;

在上面的例子中,我们使用person对象创建了一个personProxy对象,通过这个Proxy对象我们可以对person对象进行一些操作。

当我们操作name属性,Proxy对象执行了里面get方法,而当我们尝试修改age属性里面值的时候,执行了set方法。


那么Proxy模式适合用在什么地方呢?有时候当我们获取一个对象值或者修改一个对象值的时候,可能还需要做一些额外的副作用操作,比如说校验获取或者传入的值,打log之类的。而且使用Proxy对象来操作目标对象能保证对象的数据不会被污染。

更多方法

Reflect

在编写proxy中的get和set方法时候,除了直接操作原来的对象,我们还可以使用reflect来操作,正如它的名字,它是一个反射,能把操作反射在自己身上。但是实际上和直接操作是没有什么区别的,相当于一个,emmm,快捷方式?如果对一些数据操作有特别需求的可以尝试用一下,但是一般get和set感觉没什么区别。

const person = {
  name: "max",
  age: 21,
};
const personProxy = new Proxy(person, {
  get(obj, prop) {
    console.log(Reflect.get(obj, prop));
    return Reflect.get(obj, prop);
  },
  set(obj, prop, value) {
    Reflect.set(obj, prop, value);
    console.log(Reflect.get(obj, prop));
  },
});
personProxy.name;
personProxy.age = 22;

注意看get 和set 的部分,可以看到Reflect其实和基本的直接操作是没什么区别的,但是除了这些基本用法以外,Reflect还有其它的一些方法,如表

Reflect方法类似于
Reflect.apply(target, thisArgument, argumentsList)Function.prototype.apply()
Reflect.construct(target, argumentsList[, newTarget])new target(…args)
Reflect.defineProperty(target, prop, attributes)Object.defineProperty()
Reflect.deleteProperty(target, prop)delete target[name]
Reflect.get(target, prop[, receiver])target[name]
Reflect.getOwnPropertyDescriptor(target, prop)Object.getOwnPropertyDescriptor()
Reflect.getPrototypeOf(target)Object.getPrototypeOf()
Reflect.has(target, prop)in 运算符
Reflect.isExtensible(target)Object.isExtensible()
Reflect.ownKeys(target)Object.keys()
Reflect.preventExtensions(target)Object.preventExtensions()
Reflect.set(target, prop, value[, receiver])target[prop] = value
Reflect.setPrototypeOf(target, prototype)Object.setPrototypeOf()

参考

Proxy Pattern (patterns.dev)

Proxy是代理,Reflect是干嘛用的? « 张鑫旭-鑫空间-鑫生活 (zhangxinxu.com)