Javascript 简明教程

JavaScript - Optional Chaining

JavaScript 中的可选链允许您访问对象中的嵌套属性和方法,而不必检查每个属性的存在性。这有助于让您的代码更简练、易于阅读。

可选链操作符(?。)用于在 JavaScript 中实现可选链。它应放置在您希望访问的属性或方法之前。如果属性或方法不存在,该表达式将会评估为 undefined,而不是引发错误。

The Non-existing Property Problem

我们通过非现有属性问题来了解 JavaScript 中对于可选链的需求。

使用 JavaScript 中的对象时,对象中可能会有动态属性。部分属性还包含对象本身,即所谓的嵌套对象。

如果您尝试访问不存在父项的嵌套属性,JavaScript 会引发错误。

例如,

const parent = {
    child: {
        name: "Smith",
    }
}
const name = parent.child.name;

父对象包含 "ch" 属性,并且 "ch" 属性包含嵌套对象作为值。

在代码中,您访问 "child" 嵌套对象的 "name" 属性,但是 "child" 属性在父对象中不存在。因此,在您访问未定义属性时,JavaScript 就会引发以下错误。

Uncaught TypeError: Cannot read properties of undefined

为了解决上面的问题,ES11 之前使用 "&&" 操作符。

例如,

if (parent.child && parent.child.name) {
   // access parent.child.name here
}

在上面的代码中,我们首先检查是否存在 parent.child。如果是,我们访问其 name 属性以避免错误。

您获得了这个解决方案,但是如果需要从对象的第 4 或第 5 层访问该属性怎么办?您需要使用多个 && 操作符并编写复杂的代码。

此处,可选链操作符(?。)出现在画面中,以轻松解决非现有属性问题。

What is an Optional Chaining in JavaScript?

在 JavaScript 中,可选链操作符(?。)在 ECMAScript 2020(ES2020)中引入。它提供了访问对象属性、数组元素等的最佳方法。

可选链与用于访问对象嵌套属性的普通链非常相似。它在访问对象属性前检查嵌套属性是否存在,以避免错误。

Syntax

您可以遵循以下语法在 JavaScript 中使用可选链操作符。

Obj?.prop1?.nestedprop; // Accessing nested properties
Obj?.[expression]; // Accessing object property via expression
Array?.[index]; // Accessing array element
funcName?.(); // Executing the funciton
  1. 在上面的语法中,如果存在 obj 对象,它将访问 prop1 属性。代码再次检查 prop1 属性是否在 obj 对象中存在,它将访问 nestedProp 属性。否则,其将停止执行代码以避免错误。

  2. 您还可以使用表达式和可选链访问对象属性值。

  3. 可选链还可以用于访问数组元素和执行函数。

Return value

如果某个属性不存在,则可选链返回 undefined,而不会引发任何错误。

Example

在下面的示例中,car 对象包含 info 嵌套对象。info 对象包含 color 和 price 属性。

我们尝试使用可选链访问 info 对象的 price 属性,它返回 5000000。

然后,我们尝试使用可选链访问 car 对象的 engine 属性的 gears 属性。在输出中,你可以看到它返回 undefined,而不是引发错误。

<html>
<body>
   <div id = "output1">The price of the Audi Q6 is: </div>
   <div id = "output2">Total gears in the Audi Q6 is: </div>
   <script>
      const car = {
         brand: "Audi",
         model: "Q6",
         info: {
            price: 5000000,
            color: "Black",
         }
      }
      document.getElementById("output1").innerHTML += car.info?.price;
      document.getElementById("output2").innerHTML += car.engine?.gears;
   </script>
</body>
</html>
The price of the Audi Q6 is: 5000000
Total gears in the Audi Q6 is: undefined

Optional Chaining with Function Calls

在 JavaScript 中,你还可以将可选链与函数调用一起使用。如果该函数未定义,它将返回 undefined。否则,代码将执行该函数。

Example

在下面的代码中,我们对对象方法使用了可选链。

car 对象包含 getBrand() 方法。我们使用可选链执行 getBrand() 方法,该方法返回 'Audi'。

此外,我们尝试使用可选链执行 car 对象的 getColor() 方法。它返回 undefined,因为 car 对象不包含 getColor() 方法。

<html>
<body>
   <div id = "output1">The brand of the car is: </div>
   <div id = "output2">The color of the car is: </div>
   <script>
      const car = {
         getBrand() {
            return "Audi";
         },
      }
      document.getElementById("output1").innerHTML += car.getBrand?.();
      document.getElementById("output2").innerHTML += car.getColor?.();
   </script>
</body>
</html>
The brand of the car is: Audi
The color of the car is: undefined

Optional Chaining with Expression

你可以使用可选链访问对象属性时使用表达式或数组元素。

Example

在下面的代码中,animal 对象包含name 和 info 属性。info 属性再次包含具有 legs 和 tail 属性的嵌套对象。

我们使用可选链和表达式访问对象属性。你可以看到它在代码中打印输出,而不会引发任何错误,即使 'specs' 属性在 animal 对象中不存在也是如此。

<html>
<body>
   <div id = "output1">Total number of legs of the tiger is: </div>
   <div id = "output2">The color of the tiger is: </div>
   <script>
      const animal = {
         name: "Tiger",
         info: {
            legs: 4,
            tail: 1,
         }
      }
      document.getElementById("output1").innerHTML += animal.info?.["legs"];
      document.getElementById("output2").innerHTML += animal.specs?.["color"];
   </script>
</body>
</html>
Total number of legs of the tiger is: 4
The color of the tiger is: undefined

Optional Chaining with the "delete" Operator

JavaScript delete 运算符用于删除对象属性。如果你尝试删除不存在的属性,代码将引发错误。因此,你可以将可选链运算符与 delete 运算符一起使用。

Example

在下面的代码中,我们使用 delete 运算符删除嵌套 info 对象的 legs 属性和 'specs' 嵌套对象的 tail 属性,并使用可选链访问属性。

animal 对象不包含 specs 属性。尽管如此,由于可选链,代码仍然可以毫无错误地运行。

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const animal = {
         name: "Tiger",
         info: {
            legs: 4,
            tail: 1,
         }
      }
      delete animal.info?.legs;
      delete animal.sepcs?.tail;
      document.getElementById("demo").innerHTML =
      "Updated object is: " + JSON.stringify(animal);
   </script>
</body>
</html>
Updated object is: {"name":"Tiger","info":{"tail":1}}

Short-circuiting with Optional Chaining

在 JavaScript 中,短路的意思是每当你遇到错误时,就会停止代码的执行。你可以使用可选链访问对象的每个嵌套属性,以避免任何错误并在发生错误时停止代码执行。

Example

在下面的代码中,animal 对象包含 info 对象,info对象包含 legs 对象。我们使用可选链访问每个嵌套属性。因此,如果任何属性不存在,它将返回 undefined 并避免错误。

<html>
<body>
   <div id = "output1">The size of the first leg is: </div>
   <div id = "output2"> The size of the third leg is: </div>
   <script>
      const animal = {
         name: "Tiger",
         info: {
            legs: {
               first: 1.32,
               second: 1.31,
            },
            tail: 1,
         }
      }
      document.getElementById("output1").innerHTML += animal?.info?.legs?.first;
      document.getElementById("output2").innerHTML += animal?.specs?.legs?.third;
    </script>
</body>
</html>
The size of the first leg is: 1.32
The size of the third leg is: undefined

Nullish Coalescing Operator with Optional Chaining

当任何对象属性不存在时,可选链停止代码执行并返回 undefined。如果你将 JavaScript nullish 归并运算符与它一起使用,则当对象属性不存在时,你可以返回默认值。

Example

在下面的代码中,我们尝试访问 'animal' 对象的 'specs' 对象的 color 属性。这里,'specs' 在 animal 对象中不存在。因此,由于我们使用了 nullish 归并运算符,它返回 'red'。

<html>
<body>
   <div id = "output">The color of the animal is: </div>
   <script>
      const animal = {
         name: "Tiger",
         info: {
            legs: 2,
            tail: 1,
         }
      }
      animal.info?.legs;
      const color = animal?.spec?.color ?? "Red";
      document.getElementById("output").innerHTML += color;
   </script>
</body>
</html>
The color of the animal is: Red

简单来说,在需要访问动态对象的属性以避免错误的任何地方都可以使用可选链运算符。