- Javascript 基础教程
- Javascript - 首页
- JavaScript - 路线图
- JavaScript - 概述
- JavaScript - 特性
- JavaScript - 启用
- JavaScript - 放置位置
- JavaScript - 语法
- JavaScript - Hello World
- JavaScript - Console.log()
- JavaScript - 注释
- JavaScript - 变量
- JavaScript - let 语句
- JavaScript - 常量
- JavaScript - 数据类型
- JavaScript - 类型转换
- JavaScript - 严格模式
- JavaScript - 保留关键字
- JavaScript 运算符
- JavaScript - 运算符
- JavaScript - 算术运算符
- JavaScript - 比较运算符
- JavaScript - 逻辑运算符
- JavaScript - 按位运算符
- JavaScript - 赋值运算符
- JavaScript - 条件运算符
- JavaScript - typeof 运算符
- JavaScript - 空值合并运算符
- JavaScript - 删除运算符
- JavaScript - 逗号运算符
- JavaScript - 分组运算符
- JavaScript - Yield 运算符
- JavaScript - 展开运算符
- JavaScript - 幂运算符
- JavaScript - 运算符优先级
- JavaScript 控制流
- JavaScript - If...Else
- JavaScript - While 循环
- JavaScript - For 循环
- JavaScript - For...in
- Javascript - For...of
- JavaScript - 循环控制
- JavaScript - Break 语句
- JavaScript - Continue 语句
- JavaScript - Switch Case
- JavaScript - 用户定义迭代器
- JavaScript 函数
- JavaScript - 函数
- JavaScript - 函数表达式
- JavaScript - 函数参数
- JavaScript - 默认参数
- JavaScript - Function() 构造函数
- JavaScript - 函数提升
- JavaScript - 自执行函数
- JavaScript - 箭头函数
- JavaScript - 函数调用
- JavaScript - Function call()
- JavaScript - Function apply()
- JavaScript - Function bind()
- JavaScript - 闭包
- JavaScript - 变量作用域
- JavaScript - 全局变量
- JavaScript - 智能函数参数
- JavaScript 对象
- JavaScript - Number
- JavaScript - Boolean
- JavaScript - Strings
- JavaScript - Arrays
- JavaScript - Date
- JavaScript - DataView
- JavaScript - Handler
- JavaScript - Math
- JavaScript - RegExp
- JavaScript - Symbol
- JavaScript - Sets
- JavaScript - WeakSet
- JavaScript - Maps
- JavaScript - WeakMap
- JavaScript - 可迭代对象
- JavaScript - Reflect
- JavaScript - TypedArray
- JavaScript - 模板字面量
- JavaScript - 带标签的模板
- 面向对象的 JavaScript
- JavaScript - 对象
- JavaScript - 类
- JavaScript - 对象属性
- JavaScript - 对象方法
- JavaScript - 静态方法
- JavaScript - 显示对象
- JavaScript - 对象访问器
- JavaScript - 对象构造函数
- JavaScript - 原生原型
- JavaScript - ES5 对象方法
- JavaScript - 封装
- JavaScript - 继承
- JavaScript - 抽象
- JavaScript - 多态
- JavaScript - 解构赋值
- JavaScript - 对象解构
- JavaScript - 数组解构
- JavaScript - 嵌套解构
- JavaScript - 可选链
- JavaScript - 全局对象
- JavaScript - Mixins
- JavaScript - 代理
- JavaScript 版本
- JavaScript - 历史
- JavaScript - 版本
- JavaScript - ES5
- JavaScript - ES6
- ECMAScript 2016
- ECMAScript 2017
- ECMAScript 2018
- ECMAScript 2019
- ECMAScript 2020
- ECMAScript 2021
- ECMAScript 2022
- JavaScript 异步
- JavaScript - 异步
- JavaScript - 回调函数
- JavaScript - Promise
- JavaScript - Async/Await
- JavaScript - 微任务
- JavaScript - Promise 化
- JavaScript - Promise 链式调用
- JavaScript - 定时事件
- JavaScript - setTimeout()
- JavaScript - setInterval()
- JavaScript Cookie
- JavaScript - Cookie
- JavaScript - Cookie 属性
- JavaScript - 删除 Cookie
- JavaScript 浏览器 BOM
- JavaScript - 浏览器对象模型
- JavaScript - Window 对象
- JavaScript - Document 对象
- JavaScript - Screen 对象
- JavaScript - History 对象
- JavaScript - Navigator 对象
- JavaScript - Location 对象
- JavaScript - Console 对象
- JavaScript Web API
- JavaScript - Web API
- JavaScript - History API
- JavaScript - Storage API
- JavaScript - Forms API
- JavaScript - Worker API
- JavaScript - Fetch API
- JavaScript - Geolocation API
- JavaScript 事件
- JavaScript - 事件
- JavaScript - DOM 事件
- JavaScript - addEventListener()
- JavaScript - 鼠标事件
- JavaScript - 键盘事件
- JavaScript - 表单事件
- JavaScript - Window/Document 事件
- JavaScript - 事件委托
- JavaScript - 事件冒泡
- JavaScript - 事件捕获
- JavaScript - 自定义事件
- JavaScript 错误处理
- JavaScript - 错误处理
- JavaScript - try...catch
- JavaScript - 调试
- JavaScript - 自定义错误
- JavaScript - 扩展错误
- JavaScript 重要关键字
- JavaScript - this 关键字
- JavaScript - void 关键字
- JavaScript - new 关键字
- JavaScript - var 关键字
- JavaScript HTML DOM
- JavaScript - HTML DOM
- JavaScript - DOM 方法和属性
- JavaScript - DOM Document
- JavaScript - DOM 元素
- JavaScript - DOM 属性 (Attr)
- JavaScript - DOM 表单
- JavaScript - 更改 HTML
- JavaScript - 更改 CSS
- JavaScript - DOM 动画
- JavaScript - DOM 导航
- JavaScript - DOM 集合
- JavaScript - DOM NodeList
- JavaScript - DOM DOMTokenList
- JavaScript 杂项
- JavaScript - Ajax
- JavaScript - 异步迭代
- JavaScript - Atomics 对象
- JavaScript - Rest 参数
- JavaScript - 页面重定向
- JavaScript - 对话框
- JavaScript - 页面打印
- JavaScript - 验证
- JavaScript - 动画
- JavaScript - 多媒体
- JavaScript - 图像映射
- JavaScript - 浏览器
- JavaScript - JSON
- JavaScript - 多行字符串
- JavaScript - 日期格式
- JavaScript - 获取日期方法
- JavaScript - 设置日期方法
- JavaScript - 模块
- JavaScript - 动态导入
- JavaScript - BigInt
- JavaScript - Blob
- JavaScript - Unicode
- JavaScript - 浅拷贝
- JavaScript - 调用栈
- JavaScript - 引用类型
- JavaScript - IndexedDB
- JavaScript - Clickjacking 攻击
- JavaScript - 柯里化
- JavaScript - 图形
- JavaScript - Canvas
- JavaScript - 防抖
- JavaScript - 性能
- JavaScript - 样式指南
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
简单来说,您可以在需要访问动态对象的属性以避免错误的任何地方使用可选链运算符。