设计模式 - 代理模式

本文详细介绍了JavaScript中的Proxy对象如何作为代理,控制对象交互行为,包括get和set处理程序的应用。还探讨了使用Proxy进行数据验证和性能权衡的问题。
摘要由CSDN通过智能技术生成

使用代理对象,我们可以对与某些对象的交互进行更多的控制。代理对象可以在我们与对象进行交互时确定其行为,例如,当我们获取值或设置值时。

一般来说,代理是指代替他人的人。你不是直接和那个人说话,而是和代表你试图联系的人说话的代理。在JavaScript中也是如此:我们不是直接与目标对象交互,而是与Proxy对象交互。

让我们创建一个代表约翰·多伊的人物对象。

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 代理。当尝试修改属性时,从而在Proxy上调用 set 方法,我们希望代理记录属性的先前值和新值。当尝试访问属性时,从而在Proxy上调用 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;
  },
});

让我们看看当我们尝试修改或检索属性时会发生什么。

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

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;
    return true;
  }
});

personProxy.name;
personProxy.age = 43;

访问 name 属性时,代理返回了一个听起来更好的句子:The value of name is John Doe

修改 age 属性时,代理返回此属性的上一个值和新值:Changed age from 42 to 43

代理可用于添加验证。用户不应能够将person的年龄更改为字符串值,或为其指定空名称。或者,如果用户试图访问对象上不存在的属性,我们应该让用户知道。

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    if (!obj[prop]) {
      console.log(
        `Hmm.. this property doesn't seem to exist on the target object`
      );
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) => {
    if (prop === "age" && typeof value !== "number") {
      console.log(`Sorry, you can only pass numeric values for age.`);
    } else if (prop === "name" && value.length < 2) {
      console.log(`You need to provide a valid name.`);
    } else {
      console.log(`Changed ${prop} from ${obj[prop]} to ${value}.`);
      obj[prop] = value;
    }
  },
});

让我们看看当我们尝试传递错误值时会发生什么!

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    if (!obj[prop]) {
      console.log(`Hmm.. this property doesn't seem to exist`);
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) => {
    if (prop === "age" && typeof value !== "number") {
      console.log(`Sorry, you can only pass numeric values for age.`);
    } else if (prop === "name" && value.length < 2) {
      console.log(`You need to provide a valid name.`);
    } else {
      console.log(`Changed ${prop} from ${obj[prop]} to ${value}.`);
      obj[prop] = value;
    }
    return true;
  }
});

personProxy.nonExistentProperty;
personProxy.age = "44";
personProxy.name = "";

代理确保我们没有使用错误的值修改 person 对象,这有助于我们保持数据纯净!

Reflect

JavaScript 提供了一个名为 Reflect 的内置对象,这使我们在使用代理时更容易操作目标对象。

以前,我们尝试通过直接获取或设置带有括号表示法的值来修改和访问代理中目标对象的属性。相反,我们可以使用 Reflect 对象。Reflect 对象上的方法与handler对象上的方法同名。

我们可以通过 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 对象轻松访问和修改目标对象的属性。

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

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}`);
    return Reflect.set(obj, prop, value);
  }
});

personProxy.name;
personProxy.age = 43;
personProxy.name = "Jane Doe";

权衡

代理是添加对对象行为的控制的强大方法。代理可以有各种用例:它可以帮助验证、格式化、通知或调试。

过度使用 Proxy 对象或对每个handler方法调用执行繁重操作很容易对应用程序的性能产生负面影响。最好不要对性能关键代码使用代理。

  • 27
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值