JavaScript - 代理 (dài lǐ)



JavaScript 中的代理 (dài lǐ)

JavaScript 的代理是允许你包装特定对象并自定义对象基本操作(例如获取和设置对象属性)的对象。简而言之,使用代理对象,你可以为对象添加自定义行为。代理用于实现诸如日志记录、缓存和安全之类的功能。

我们可以使用 JavaScript 中的 Proxy() 构造函数创建一个代理对象。构造函数接受两个参数——目标对象和处理程序对象。它返回目标对象的新代理对象。

语法 (yǔ fǎ)

以下是 JavaScript 中创建代理对象的语法:

const obj = new Proxy(targetObj, Handler);

我们在上面的语法中使用了带有 new 关键字的 Proxy() 构造函数。

参数 (cān shù)

Proxy 构造函数接受两个参数。

  • targetObj − 这是你想要为其创建代理对象并自定义其默认行为的目标对象。

  • Handler − 这是一个包含自定义目标对象行为的功能的对象。

示例 (shì lì)

在下面的示例中,person 对象包含 name 和 age 属性。

我们为名为 proxyObj 的 person 对象定义了代理对象。此外,我们将 handler 对象作为 Proxy() 构造函数参数传递。

在 handler 对象中,我们定义了 getter 来访问对象属性。getter 检查对象是否包含你正在查找的属性。如果是,则返回属性值。否则,它返回一条消息,说明对象不包含该属性。

<html>
<body>
   <div id = "demo1">The name of the person is: </div>
   <div id = "demo2">The height of the person is: </div>
   <script>
      const person = {
         name: "Same",
         age: 32,
      }
      const handler = {
         // Defining the getters
         get: function (object, property) {
            return object[property] ? object[property] : 
            'Object doesnt contain the property.';
         }
      }
      const proxyObj = new Proxy(person, handler);
      document.getElementById("demo1").innerHTML += proxyObj.name;
      document.getElementById("demo2").innerHTML += proxyObj.height;
   </script>
</body>
</html>

输出 (shū chū)

The name of the person is: Same
The height of the person is: Object doesnt contain the property.

当您从对象访问不存在的属性时,它将返回 undefined。在这里,我们自定义了对象的默认行为以返回一种友好易读的方式。

如果在创建代理对象时传递空 handler 对象,则代理对象的工作方式与原始对象相同。

JavaScript 代理处理程序 (dài lǐ chǔ lǐ chéng xù)

JavaScript 中有多个代理处理程序可用,我们下面介绍了其中一些。代理处理程序用于覆盖对象的默认行为。

JavaScript get() 代理处理程序 (dài lǐ chǔ lǐ chéng xù)

JavaScript 中的 get() 代理处理程序允许你更改对象的属性访问行为。

语法 (yǔ fǎ)

请按照以下语法使用带有代理对象的 get() 代理处理程序。

get(target, property, receiver)

参数 (cān shù)

  • target − 这是目标对象。

  • property − 这是需要访问其值的属性。

  • receiver − 它本身就是一个代理对象。

示例 (shì lì)

在下面的代码中,watch 对象包含 brand、color 和 price 属性。我们已经为 watch 对象创建了代理。

handler 对象包含 get() 处理程序,如果属性存在则返回属性值。否则,它返回一条易读的消息。

<html>
<body>
   <div id = "output1">Brand:  </div>
   <div id = "output2">Price:  </div>
   <script>
      const watch = {
         brand: "Casio",
         color: "Blue",
         price: null,
      }

      const handler = {
         get(object, property) {
            return object[property] != null ? object[property] : "Property is null.";
         }
      }
      const wathcProxy = new Proxy(watch, handler);
      document.getElementById("output1").innerHTML += wathcProxy.brand;
      document.getElementById("output2").innerHTML += wathcProxy.price;
   </script>
</body>
</html>

输出 (shū chū)

Brand: Casio
Price: Property is null.

JavaScript set() 代理处理程序 (dài lǐ chǔ lǐ chéng xù)

JavaScript 中的 set() 代理处理程序用于更改更新对象属性的默认行为。

语法 (yǔ fǎ)

请按照以下语法使用 set() 代理处理程序。

set(target, property, value, receiver)

参数 (cān shù)

  • target − 这是目标对象。

  • property − 这是要更改其值的属性。

  • value − 这是更新后的值。

  • receiver − 它本身就是一个代理对象。

示例 (shì lì)

在下面的代码中,handler 对象包含 set() 代理处理程序。set() 处理程序检查属性是否等于“price”。如果是,则使用新值更新属性值。否则,它将“不可用”设置为对象属性。

<html>
<body>
   <p id = "demo"> </p>
   <script>
      const output = document.getElementById("demo");
      const watch = {
         brand: "Casio",
         color: "Blue",
         price: null,
      }
      const handler = {
         set(object, property, value) {
            if (property === "price") {
               object[property] = value;
            }
            else {
               object[property] = "Not Available";
            }
         }
      }
      const wathcProxy = new Proxy(watch, handler);
      wathcProxy.price = 2000;
      wathcProxy.dial = "Round";
      output.innerHTML += "Price: " + wathcProxy.price + "<br>";
      output.innerHTML += "Dial: " + wathcProxy.dial + "<br>";
   </script>
</body>
</html>

输出 (shū chū)

Price: 2000
Dial: Not Available

JavaScript apply() 代理处理程序 (dài lǐ chǔ lǐ chéng xù)

apply() 代理处理程序用于更改函数调用的默认行为。

语法 (yǔ fǎ)

请按照以下语法使用 apply() 代理处理程序。

apply(target, thisArg, arguments)

参数 (cān shù)

  • target − 这是需要执行的目标函数。

  • thisArg − 它指的是上下文,其元素应在函数体中使用 this 关键字访问。

  • arguments − 这是要传递给函数的参数数组。

示例 (shì lì)

在下面的代码中,getDetails 是为 getWatchDetails() 函数创建的代理对象。handler 对象包含 apply() 方法并调用目标函数。

我们通过传递 watch 对象作为参数来调用 getDetails() 代理。

<html>
<body>
   <p id = "output"> </p>
   <script>
      const watch = {
         brand: "Casio",
         color: "Blue",
         price: 2000,
      }
      const getWatchDetails = function (watch) {
         return `Brand: ${watch.brand},  
         Color: ${watch.color}, 
         price: ${watch.price}`;
      }
      const getDetails = new Proxy(getWatchDetails, {
         apply(target, thisArg, args) {
            return target(...args).toUpperCase();
         }
      });
      document.getElementById("output").innerHTML += getDetails(watch);
   </script>
</body>
</html>

输出 (shū chū)

BRAND: CASIO, COLOR: BLUE, PRICE: 2000

JavaScript 中代理对象的用途 (yòng tú)

本文将结合示例讲解使用代理对象的好处。

用于验证

你可以在 JavaScript 中使用代理对象来验证属性值,同时更新属性值或向对象添加新属性。

示例 (shì lì)

在下面的代码中,numbers 对象包含 num1、num2 和 num3 属性。set() 代理处理器检查新值是否大于当前值。如果是,则更新值;否则,保留旧值。

<html>
<body>
   <p id = "demo"> </p>
   <script>
      const output = document.getElementById("demo");
      const numbers = {
         num1: 10,
         num2: 20,
         num3: 30,
      }
      const handler = {
         set(object, property, value) {
            if (value > object[property]) { 
               // Validing the new value using the previous value
               object[property] = value;
            }
         }
      }
      const numberProxy = new Proxy(numbers, handler);
      numberProxy.num1 = 20;
      numberProxy.num2 = 10;

      output.innerHTML += "num1: " + numbers.num1 + ", num2: " + numbers.num2;
   </script>
</body>
</html>

输出 (shū chū)

num1: 20, num2: 20

用于访问控制

你也可以使用代理处理器来控制 JavaScript 中对象的访问。例如,你可以限制用户更新对象属性,使其成为只读。

示例 (shì lì)

在下面的代码中,每当你尝试更新对象属性值时,它都会打印一条消息,指出该对象是只读的。

<html>
<body>
   <p id = "demo"> </p>
   <script>
      const output = document.getElementById("demo");
      const numbers = {
         num1: 10,
         num2: 20,
         num3: 30,
      }
      const handler = {
         set(object, property, value) {
            output.innerHTML += "Object is read-only.<br>"
         }
      }
      const numberProxy = new Proxy(numbers, handler);
      numberProxy.num1 = 20;
      output.innerHTML += "num1: " + numberProxy.num1;
   </script>
</body>
</html>

输出 (shū chū)

Object is read-only.
num1: 10

副作用

当任何人尝试访问或更新对象属性时,你可能会调用函数或类方法。

示例 (shì lì)

在下面的示例中,emailValidator() 函数检查电子邮件是否包含“@”。如果是,则返回 true;否则,返回 false。

在 set() 代理处理器中,我们根据 emailValidator() 函数的返回值来更新属性值。

<html>
<body>
   <p id = "output"> </p>
   <script>
      const emails = {
         email1: "abcd@gmail.com",
      }
      // Function to validate the email
      function emailValidator(email) {
         if (email.includes("@")) {
            return true;
         } else {
            return false;
         }
      }
      const handler = {
         set(object, property, value) {
            if (emailValidator(value)) {
               object[property] = value;
            }
         }
      }
      const emailProxy = new Proxy(emails, handler);
      emailProxy.email1 = "nmc@gmail.com";
      document.getElementById("output").innerHTML = 
      "email1: " + emailProxy.email1;
   </script>
</body>
</html>

输出 (shū chū)

email1: nmc@gmail.com

然而,代理处理器的用法并不局限于此,我们无法在本教程中涵盖每种用例。因此,你可以探索更多代理处理器的用例。

JavaScript 代理处理器列表

这里列出了 JavaScript 中的所有代理处理器。

代理处理器方法

序号 代理处理器 描述
1 apply() 它改变函数调用的默认行为。
2 construct() 拦截新对象的构造。
3 defineProperty() 改变定义新属性的行为。
4 deleteProperty() 改变删除新属性的行为。
5 get() 改变访问对象属性的行为。
6 getOwnPropertyDescriptor() 拦截对象的 getOwnPropertyDescriptor() 方法。
7 getPrototypeOf() 拦截内部方法。
8 has() 操纵检查对象是否包含该属性。
9 isExtensible() 拦截对象的 isExtensible() 方法。
10 ownKeys() 改变 ownKeys() 方法的行为。
11 preventExtensions() 拦截阻止对象扩展的操作。
12 set() 改变添加新属性或更新对象属性值的默认行为。
13 setPrototypeOf() 自定义 Object.setPrototypeOf() 方法。

构造函数

序号 构造函数 描述
1 Proxy() 用于创建代理对象。

静态方法

序号 方法 描述
1 revocable() 它也用于创建新的代理对象,类似于 Proxy() 构造函数。
广告
© . All rights reserved.