小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
在开发的时候经常会遇到这个场景. 有一个存在嵌套结构的对象 obj 需要访问对象深层的属性, 比如 obj.a.b.c
这个时候 如果中间某一层属性不存在, 则在读取下一层属性时, 会抛出 TypeError 的错误.
想要避免这个错误产生, 我们不得不在每一层加上一个检查, 确保其值既不是 null 也不是 undefined
const obj = {}
// before ES2020 - no checks
obj.a.b // TypeError: Cannot read property 'b' of undefined
// before ES2020 - incremental nested checks
obj.a && obj.a.b // undefined
这种增量嵌套检查的方法, 在层次深的时候会特别冗长, 既不方便书写, 也不方便阅读
let d = obj.a && obj.a.b && obj.a.b.c && obj.a.b.c.d
可选链操作符
在ES2020迎来了一个新特性: 可选链操作符 ?. 使用可选链操作符, 在访问 obj.a.b 的时候, 不用显式校验 obj.a 的状态再用短路计算拿最终结果
基本用法
我们用可选链操作符重写上面的代码:
const obj = {}
// Optional Chaining
obj.a?.b?.c?.d // undefined
可选链操作符, 提供了一种方法来简化被连接对象的值的访问, 可以安全的访问对象内部属性, 不必考虑它是否存在.
原理
那么可选运算符的底层是如何实现的呢? 我们可以用 Babel REPL 来查看转换后的js代码
转换前:
转换后:
简化以上代码使其更具有可读性:
可以看出, 使用 ?. 操作符, js会在尝试访问 obj.a.b 之前, 先隐式的检查并确定 obj.a 既不是 null 也不是 undefined. 如果是 null 或者 undefined, 表达式会短路计算直接返回 undefined.
其他用法:
访问数组:
对数组进行下标访问, 可以使用可选链操作符
let item = arr?.[40];
短路计算:
当在表达式中使用可选链时,如果左操作数是 null 或 undefined,表达式将不会被计算,例如:
let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];
console.log(x); // x 将不会被递增,依旧输出 0
babel 配置
大部分现代浏览器都支持了可选链操作符?., 为了安全并向后兼容, 还是建议在项目中配置转换插件
// 在 package.json 内 , 安装依赖
{
"devDependencies": {
"@babel/core": "^7.12.9",(7.0以下的babel包需删除)
"@babel/plugin-proposal-optional-chaining": "^7.12.7", (依赖babel 7.0以上)
"babel-loader": "^8.2.2",
...
}
...
}
// 新建文件 ".babelrc.js" (在package.json的同级目录下)
{
"plugins": [
"@babel/plugin-proposal-optional-chaining"
]
}