把握行业变革关键节点,12 月 19 日 - 20 日,AICon北京站即将重磅启幕! 了解详情
写点什么

了解 JavaScript 新特性:Optional Chaining

  • 2019-10-25
  • 本文字数:2083 字

    阅读完需:约 7 分钟

了解JavaScript新特性:Optional Chaining

Optional Chaining 是 JavaScript 的一个新特性,它允许我们在尝试访问对象的属性之前检查对象是否存在。其他语言也有类似的东西,例如,C# 的 Null Conditional 操作符,与 Optional Chaining 非常类似。


JavaScript 中的长属性访问链很容易出错,因为它们中的任何一个都可能评估为nullundefined(也称为“空”值)。要在每个步骤都中检查属性是否存在,很容易搞出来一个深层嵌套结构的if语句或一个长长的if条件复制属性访问链:


// Error prone-version, could throw.const nameLength = db.user.name.length;
// Less error-prone, but harder to read.let nameLength;if (db && db.user && db.user.name) nameLength = db.user.name.length;
复制代码


上面的代码也可以使用三元操作符表示,但并不能提高可读性。


const nameLength =  (db    ? (db.user      ? (db.user.name        ? db.user.name.length        : undefined)      : undefined)    : undefined);
复制代码

介绍 Optional Chaining 操作符

你当然不想编写这样的代码,因此希望有其他选择。其他一些语言使用了被称为“optional chaining”(可选链)的功能提供了一种优雅的解决方案。根据最近的规范提案,“Optinal Chain 是一个或多个属性访问和函数调用的链,其中第一个以令牌?.开头”。


使用新的 Optinal Chaining 操作符,我们可以重写上述示例,如下所示:


// Still checks for errors and is much more readable.const nameLength = db?.user?.name?.length;
复制代码


如果dbusernameundefinednull会发生什么?使用 Optinal Chaining 操作符时,JavaScript 会将nameLength初始化为undefined,而不是抛出错误。


请注意,此行为也比我们检查if (db && db.user && db.user.name)更加健壮。例如,如果name一直都是字符串怎么办?我们可以将name?.length更改为name.length。如果name是一个空字符串,我们仍将获得正确的0长度。这是因为空字符串是虚值:它在if子句中的行为类似false。Optinal Chaining 操作符可修复这类常见的错误。

其他语法形式:调用和动态属性

还有一个用来调用可选方法的操作符版本:


// Extends the interface with an optional method, which is present// only for admin users.const adminOption = db?.user?.validateAdminAndGetPrefs?.().option;
复制代码


这里的语法可能让人感到意外,因为?.()是实际的操作符,它适用于 之前 的表达式。


操作符还有第三种用法,就是可选的动态属性访问,通过?.[]实现。它要么返回括号中的参数所引用的值,或者如果没有可以获取值的对象,则返回undefined。按照上面的示例,下面是一个可能的用例:


// Extends the capabilities of the static property access// with a dynamically generated property name.const optionName = 'optional setting';const optionLength = db?.user?.preferences?.[optionName].length;
复制代码


最后一种形式也可用于可选的索引数组,例如:


// If the `usersArray` is `null` or `undefined`,// then `userName` gracefully evaluates to `undefined`.const userIndex = 42;const userName = usersArray?.[userIndex].name;
复制代码


需要非undefined默认值时,Optinal Chaining 操作符可以与双问号?? 操作符组合使用。这样可以使用指定的默认值进行安全的深层属性访问,从而解决了以前需要用户域库(例如 lodash 的 _.get)的常见用例:


const object = { id: 123, names: { first: 'Alice', last: 'Smith' }};
{ // With lodash: const firstName = _.get(object, 'names.first'); // → 'Alice'
const middleName = _.get(object, 'names.middle', '(no middle name)'); // → '(no middle name)'}
{ // With optional chaining and nullish coalescing: const firstName = object?.names?.first ?? '(no first name)'; // → 'Alice'
const middleName = object?.names?.middle ?? '(no middle name)'; // → '(no middle name)'}
复制代码

Optinal Chaining 操作符的属性

Optinal Chaining 操作符具有一些有趣的属性:短路、堆叠和可选删除。下面通过一个示例逐一介绍。


短路(Short-circuiting)意味着如果 Optinal Chaining 操作符提前返回,则不对表达式的其余部分求值:


// `age` is incremented only if `db` and `user` are defined.db?.user?.grow(++age);
复制代码


堆叠(Stacking)意味着可以对一系列属性访问应用多个 Optinal Chaining 操作符:


// An optional chain may be followed by another optional chain.const firstNameLength = db.users?.[42]?.names.first.length;
复制代码


尽管如此,在一条链中使用多个 Optinal Chaining 操作符前请三思。如果一个值保证不为空,则不建议使用?.访问它的属性。在上面的示例中,db被视为始终已定义,但是db.usersdb.users [42]可能未定义。如果数据库中有这样的用户,则假定始终定义names.first.length


可选删除(Optinal deletion)意味着可以将delete操作符与 Optinal Chain 结合使用:


// `db.user` is deleted only if `db` is defined.delete db?.user;
复制代码


更多信息参阅提案的语义部分


原文链接https://v8.dev/features/optional-chaining


2019-10-25 19:485060

评论

发布
暂无评论
发现更多内容

覆盖80%业务场景,原生鸿蒙出行、教育行业样板间专区上线

最新动态

交易所开发:构建安全、高效、可靠的数字资产交易平台

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

TON链上的代币开发与小程序开发:模式与要求

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

云桌面解决方案哪家好?青椒云云桌面有什么优势

青椒云云电脑

云桌面 云桌面解决方案

鸿蒙 next 写入考试时间日程到系统日历

flfljh

鸿蒙

华为账号一键登录

flfljh

鸿蒙

Web安全知识记录

天翼云开发者社区

网络安全 Web

容器、容器云和容器化PaaS平台之间到底是什么关系?

天翼云开发者社区

云计算 容器服务

Hadoop作业调度优化,提升数据处理速度的杀手锏!

敏捷调度TASKCTL

hadoop cloudera 集群搭建 HDFS写入 HDFS读取

云教室解决方案提供商-青椒云

青椒云云电脑

云教室 云教室解决方案

云桌面和云电脑有何区别?云桌面有什么作用

青椒云云电脑

云桌面 云电脑

AI 容器建设项目正式启动!龙蜥社区加速 AI 原生 OS 技术创新

OpenAnolis小助手

开源 AI 操作系统 龙蜥社区

AI助力制造工艺|利用机器学习实现泡沫浮选工艺优化

Altair RapidMiner

AI 数据分析 altair 制造业数字化 RapidMiner

云桌面和云电脑有何区别?云桌面有什么作用

青椒云云电脑

云桌面 云电脑

探讨AI 应用推广和“车用场景建设”提案,龙蜥社区召开两大委员会月度会议

OpenAnolis小助手

开源 操作系统 龙蜥社区 龙蜥社区技术委员会 龙蜥社区运营委员会

破解知识管理难题,天润融通大模型如何提高知识库管理效率?

天润融通

鸿蒙 Flutter plugin开发详细解释

flfljh

鸿蒙

鸿蒙Next简易版本通用头部导航栏开发

flfljh

鸿蒙

第二届全国高校软件测试开发教育峰会在韩山师范学院隆重举办!

霍格沃兹测试开发学社

共筑安全防线,龙蜥社区「操作系统及软件供应链安全MeetUp」邀您报名

OpenAnolis小助手

安全 操作系统 龙蜥社区 龙蜥社区安全联盟 龙蜥社区走进系列

软件测试学习笔记丨Vue常用指令-条件渲染(v-if)

测试人

软件测试

活动回顾|体验技术大会暨OpenTiny技术交流茶话会圆满结束~

OpenTiny社区

web开发 OpenTiny TinyVue TinyEngine 前端开源

蓝卓获权威认证 被评为IDC数字工厂领导者

财见

桌面云服务:未来办公新时代的探索

青椒云云电脑

桌面云 云桌面

英特尔携手龙蜥,共筑未来操作系统

OpenAnolis小助手

操作系统 龙蜥社区 龙蜥操作系统大会

【JIT/极态云】技术文档--反馈提醒

武汉万云网络科技有限公司

前端 低代码 `后端

了解JavaScript新特性:Optional Chaining_大前端_Maya Lekova_InfoQ精选文章