Javascript 简明教程

JavaScript - Proxies

Proxy in JavaScript

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

The JavaScript proxies are objects that allow you to wrap a particular object and customize the fundamental operations of the object, like getting and setting object properties. In short, using the proxy object, you can add custom behavior to the object. The proxies are used to implement features such as logging, caching, and securities.

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

We can create a proxy object using the Proxy() constructor in JavaScript. The constructor accepts two parameters – target object and handler object. It returns a new proxy object for the target object.

Syntax

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

Following is the syntax to create a proxy object in JavaScript −

const obj = new Proxy(targetObj, Handler);

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

We used the Proxy() constructor with a new keyword in the above syntax.

Parameters

Proxy 构造函数采用两个参数。

The Proxy constructor takes two parameters.

  1. targetObj − It is a target object for which you want to create a proxy object and customize its default behavior.

  2. Handler − It is an object containing the functionality to customize the behavior of the target object.

Example

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

In the example below, the person object contains the name and age property.

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

We have defined the proxy object for the person object named proxyObj. Also, we passed the handler object as a Proxy() constructor parameter.

在处理程序对象中,我们定义了访问对象属性的 getter。getter 检查对象是否包含您要查找的属性。如果是,它将返回属性值。否则,它将返回消息,说明对象不包含该属性。

In the handler object, we have defined the getters to access the object property. The getters check whether the object contains the property you are looking for. If yes, it returns the property value. Otherwise, it returns the message saying the object doesn’t contain the property.

<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>
The name of the person is: Same
The height of the person is: Object doesnt contain the property.

当您从对象访问不存在的属性时,它会返回 undefined。这里,我们自定义了对象的默认行为来返回一种简洁而可读的方法。

When you access the non-existing property from the object, it returns the undefined. Here, we have customized the object’s default behavior to return a nice and readable method.

JavaScript Proxy Handlers

JavaScript 中有多个代理处理程序可用,我们将在下面涵盖其中一些内容。代理处理程序用于覆盖对象的默认行为。

There are multiple proxy handlers available in JavaScript, and we have covered some of them below. The proxy handlers are used to override the default behavior of the object.

The JavaScript get() proxy handler

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

The get() proxy handler in JavaScript allows you to change the property accessing behavior of the object.

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

Follow the syntax below to use the get() proxy handler with the proxy object.

get(target, property, receiver)
  1. target − It is a target object.

  2. property − It is a property whose value is needed to access.

  3. receiver − It is a proxy object itself.

在下面的代码中,watch 对象包含品牌、颜色和价格属性。我们已经为 watch 对象创建了代理。

In the below code, the watch object contains the brand, color, and price property. We have created the proxy for the watch object.

处理程序对象包含 get() 处理程序,并且在没有该处理程序的情况下返回属性值。否则,它将返回一条可读消息。

The handler object contains the get() handler and returns the property value if it is not. Otherwise, it returns a readable message.

<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>
Brand: Casio
Price: Property is null.

The JavaScript set() proxy handler

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

The set() proxy handler in JavaScript is used to change the default behavior of updating the property of the object.

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

Follow the syntax below to use the set() proxy handler.

set(target, property, value, receiver)
  1. target − It is a target object.

  2. property − It is a property to change its value.

  3. value − It is an updated value.

  4. receiver − It is a proxy object itself.

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

In the below code, the handler object contains the set() proxy handler. The set() handler checks whether the property is equal to the 'price’. If yes, it updates the property value with a new value. Otherwise, it sets 'Not Available' to the object property.

<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>
Price: 2000
Dial: Not Available

The JavaScript apply() proxy handler

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

The apply() proxy handler is used to change the default behavior of the function call.

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

Follow the syntax below to use the apply() proxy handler.

apply(target, thisArg, arguments)
  1. target − It is a target function needed to execute.

  2. thisArg − It refers to the context whose elements should be accessed using this keyword in the function body.

  3. arguments − It is an array of arguments to pass to the function.

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

In the below code, getDetails is a proxy object created for the getWatchDetails() function. The handler object contains the apply() method and calls the target function.

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

We have called the getDetails() proxy by passing the watch object as a parameter.

<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>
BRAND: CASIO, COLOR: BLUE, PRICE: 2000

Uses of the Proxy Object in JavaScript

在这里,我们用示例说明了使用代理对象的好处。

Here, we have explained the benefits of using the proxy object with examples.

For Validation

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

You can use the proxy object in JavaScript to validate the property values while updating the value of the property or adding a new property to the object.

在下边的代码中,numbers 对象包含 num1、num2 和 num3 属性。set() 代理处理程序检查新值是否大于当前值。如果为真,它将更新该值。否则,它将保留旧值。

In the below code, the numbers object contains the num1, num2, and num3 properties. The set() proxy handler checks whether the new value is greater than the current value. If yes, it updates the value. Otherwise, it keeps old values.

<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>
num1: 20, num2: 20

For Access Control

您还可以使用代理处理程序控制 JavaScript 中对象的访问权限。例如,您可以限制用户更新对象属性并使其变为只读。

You can also use the proxy handler to control the access of the object in JavaScript. For example, you can restrict users from updating the object properties and making them read-only.

在下边的代码中,无论何时尝试更新对象属性值时,它都将打印对象为只读的消息。

In the below code, whenever you try to update the object property value, it prints the message that the object is read-only.

<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>
Object is read-only.
num1: 10

Side Effects

当有人尝试访问或更新对象属性时,您可以调用函数或类方法。

You may call the functions or class methods when anyone tries to access or update the object property.

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

In the example below, the emailValidator() function checks whether the email includes the '@'. If yes, it returns true. Otherwise, it returns false.

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

In the set() proxy handler, we update the property value based on the returned value of the emailValidator() function.

<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>
email1: nmc@gmail.com

但是,代理处理程序的使用并不受限制,我们无法在本教程中涵盖每种用例。因此,您可以探索更多代理处理程序的用例。

However, usage of the proxy handers is not limited, and we can’t cover each use case in this tutorial. So, you may explore more use cases of the proxy handlers.

JavaScript Proxy Handlers List

在这里,我们列出了 JavaScript 中的所有代理处理程序。

Here, we have listed all proxy handlers in JavaScript.

Proxy Handler Methods

Sr.No.

Proxy Handler

Description

1

apply()

It changes the default behavior of the function call.

2

construct()

Trapping the construction of new object.

3

defineProperty()

Changing the behavior of defining new property.

4

deleteProperty()

Changing the behavior of deleting the new property.

5

get()

Changing the behavior of accessing object property.

6

getOwnPropertyDescriptor()

To trap the getOwnPropertyDescriptor() method of the object.

7

getPrototypeOf()

Trapping the internal methods.

8

has()

To manipulate the checking of whether an object contains the property.

9

isExtensible()

To trap the isExtensible() method of the Object.

10

ownKeys()

To change the behavior of the ownKeys() method.

11

preventExtension()

To trap the preventing extension of the object.

12

set()

To change the default behavior of adding new property or updating a property value of the object.

13

setPrototypeOf()

To customize the Object.setPrototypeOf() method.

Constructor

Sr.No.

Constructor

Description

1

Proxy()

It is used to create a proxy object.

Static Method

Sr.No.

Method

Description

1

revocable()

It is also used to create a new proxy object similar to the Proxy() constructor.