在 JavaScript 中,可选链允许你在不检查每个属性是否存在的情况下访问嵌套的对象属性和方法。这可以帮助使你的代码更简洁且易于阅读。
可选链的引入
可选链操作符 (?.
) 被用来实现 JavaScript 中的可选链。它放置在你想访问的属性或方法之前。如果该属性或方法不存在,表达式将评估为 undefined
而不是抛出错误。
非存在属性问题
让我们通过非存在的属性问题来理解 JavaScript 中引入可选链的必要性。
在 JavaScript 中工作时,你可能会遇到具有动态属性的对象。一些属性也包含对象作为值,称为嵌套对象。
如果尝试访问其父级不存在的嵌套属性,JavaScript 可能会抛出错误。
例如,
const parent = {
child: {
name: "Smith",
}
}
const name = parent.child.name;
在这个例子中,父对象包含 'child'
属性,并且 'child'
属性包含一个嵌套对象作为值。
在代码中,你访问 'child'
嵌套对象的 'name'
属性,但如果 'child'
属性不存在于父对象中,那么 JavaScript 将会抛出以下错误:
Uncaught TypeError: Cannot read properties of undefined
为了解决上述问题,在 ES11 之前通常使用 &&
操作符。
例如,
if (parent.child && parent.child.name) {
}
在上面的代码中,我们首先检查 parent.child
是否存在。如果存在,则访问其 name
属性以避免错误。
尽管找到了解决方案,但是如果需要从对象的第四级或第五级访问属性呢?你需要使用多个 &&
操作符并编写复杂的代码。
此时,可选链操作符 (?.
) 就派上用场,可以轻松解决非存在属性的问题。
什么是 JavaScript 中的可选链?
在 JavaScript 中,可选链操作符 (?.
) 于 ECMAScript 2020 (ES2020) 中引入。它提供了一种最好的方式来访问对象属性、数组元素等。
可选链与用于访问对象嵌套属性的正常链非常相似。它会在访问对象属性之前检查嵌套属性是否存在以避免错误。
语法
你可以按照以下语法在 JavaScript 中使用可选链操作符:
Obj?.prop1?.nestedprop;
Obj?.[expression];
Array?.[index];
funcName?.();
在上面的语法中,如果 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()
方法。由于 car
对象不包含 getColor()
方法,因此它返回 undefined
。
<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
属性的嵌套对象。
我们使用可选链和表达式来访问对象属性。你可以看到即使 animal
对象中不存在 'specs'
属性,代码也能无错误地打印输出。
<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.specs?.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
简而言之,你可以在任何需要访问动态对象属性以避免错误的地方使用可选链操作符。