JavaScript - 可选链



JavaScript 中的可选链允许您访问对象的嵌套属性和方法,而无需检查每个属性是否存在。这有助于使您的代码更简洁且更易于阅读。

可选链运算符 (?.) 用于在 JavaScript 中实现可选链。它放在您要访问的属性或方法之前。如果属性或方法不存在,表达式将评估为 undefined,而不是抛出错误。

不存在的属性问题

让我们通过不存在的属性问题来了解 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 层的属性怎么办?您需要使用多个 && 运算符并编写复杂的代码。

在这里,可选链运算符 (?. ) 出现以轻松解决不存在的属性问题。

什么是 JavaScript 中的可选链?

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

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

语法

您可以按照以下语法在 JavaScript 中使用可选链运算符。

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

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

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

返回值

如果属性不存在,可选链将返回 undefined 而不抛出任何错误。

示例

在下面的示例中,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

带有函数调用的可选链

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

示例

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

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

带有表达式的可选链

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

示例

在下面的代码中,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

带有 "delete" 运算符的可选链

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

示例

在下面的代码中,我们使用 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}}

可选链的短路

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

示例

在下面的代码中,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

可选链与空值合并运算符

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

示例

在下面的代码中,我们尝试访问 'animal' 对象的 'specs' 对象的 color 属性。这里,'specs' 不存在于 animal 对象中。因此,它返回 '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

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

广告