可选链运算符(?.)
bug收集:专门解决与收集bug的网站
网址:www.bugshouji.com
今天给大家分享可选链运算符(?.)
背景:
在 ES2020 之前,如果要访问 JavaScript 中对象的嵌套属性,则必须在每个级别检查是否为 null 或 undefined,否则最终将会抛出 TypeError。
为了避免出现 TypeError,我们将不得不创建临时变量或执行一系列增量 && 调用,这看起来很丑陋,并且同时占用了空间和时间。
例如:
const obj = {
prop: {
a: "value"
}
}
// before ES2020 - no checks
obj.foo.a // TypeError: Cannot read property 'a' of undefined
// before ES2020 - incremental nested checks
obj.foo && obj.foo.b // undefined
在ES2020中,通过可选链运算符 ?.
,现在我们就可以内联进行这些检查了。
官方定义:
可选链运算符(?.)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 运算符的功能类似于 . 链式运算符,不同之处在于,在引用为空 (nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。 mdn
语法:
obj.val?.prop
obj.val?.[expr]
obj.func?.(args)
描述
可选链与对象的引用
可选链运算符之前,对象引用是为了避免出错,使用用&&来验证
let nestedProp = obj.first && obj.first.second;
有了可选链运算符(?.),在访问 obj.first.second 之前,不再需要明确地校验 obj.first 的状态,再并用短路计算获取最终结果:
let nestedProp = obj.first?.second;
通过使用 ?. 运算符取代 . 运算符,JavaScript 会在尝试访问 obj.first.second 之前,先隐式地检查并确定 obj.first 既不是 null 也不是 undefined。如果obj.first 是 null 或者 undefined,表达式将会短路计算直接返回 undefined。
这等价于以下表达式,但实际上没有创建临时变量:
let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);
可选链与函数调用
函数调用时如果被调用的方法不存在,使用可选链可以使表达式自动返回undefined
而不是抛出一个异常。
let result = someInterface.customMethod?.();
注: 如果存在一个属性名且不是函数,使用 ?. 仍然会产生一个 TypeError 异常 (x.y is not a function).
处理可选的回调函数或者事件处理器
使用?.的你可以忽略这些额外的校验
// ES2019 的写法
function doSomething(onContent, onError) {
try {
// ... do something with the data
}
catch (err) {
if (onError) { // 校验 onError 是否真的存在
onError(err.message);
}
}
}
// 使用可选链进行函数调用
function doSomething(onContent, onError) {
try {
// ... do something with the data
}
catch (err) {
onError?.(err.message); // 如果 onError 是 undefined 也不会有异常
}
}
可选链和表达式
当使用方括号与属性名的形式来访问属性时,你也可以使用可选链运算符:
let nestedProp = obj?.['prop' + 'Name'];
可选链不能用于赋值
let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
可选链访问数组元素
let arrayItem = arr?.[42];
基本例子
如下的例子在一个不含 bar 成员的 Map 中查找 bar 成员的 name 属性,因此结果是 undefined。
let myMap = new Map();
myMap.set("foo", {name: "baz", desc: "inga"});
let nameBar = myMap.get("bar")?.name;
短路计算
当在表达式中使用可选链时,如果左操作数是 null 或 undefined,表达式将不会被计算,例如:
let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];
console.log(x); // x 将不会被递增,依旧输出 0
连用可选链运算符
可以连续使用可选链读取多层嵌套结构:
let customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls" // details 的 address 属性未有定义
}
};
let customerCity = customer.details?.address?.city;
// … 可选链也可以和函数调用一起使用
let duration = vacations.trip?.getTime?.();
使用空值合并运算符
空值合并运算符可以在使用可选链时设置一个默认值:
let customer = {
name: "Carl",
details: { age: 82 }
};
let customerCity = customer?.city ?? "暗之城";
console.log(customerCity); // “暗之城”
苟有恒 , 何必三更眠五更起
相关文章
- [javaEE] EL表达式调用java方法
- [javaEE] EL表达式获取数据
- [javaSE] 数据结构(AVL树基本概念)
- [javaSE] 数据结构(栈)
- [javaSE] 数据结构(队列)
- [javaSE] 数据结构(二叉树-遍历与查找)
- [javaSE] 数据结构(二叉查找树-插入节点)
- [javaSE] GUI(jar包双击运行)
- [javaSE] GUI(打开文件对话框)
- [javaSE] GUI(菜单)
- [javaSE] GUI(对话框Dialog)
- [javaSE] GUI(练习-列出指定目录内容)
- [javaEE] 控制浏览器缓存资源
- [javaEE] response实现图片下载
- [javaSE] GUI(鼠标事件)
- [javaSE] 网络编程(TCP-并发上传图片)
- [javaSE] IO流(装饰设计模式)
- [javaSE] 集合框架(Map概述)
- [javaSE] 多线程(join方法)
- [javaSE] 多线程(守护线程)