《HarmonyOS:领航者说》技术公开课来啦,大咖分享、实战解码,不容错过 了解详情
写点什么

了解 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:484465

评论

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

IPv6基础知识

穿过生命散发芬芳

ipv6 8月月更

构建在Findora上的Forlend,具备隐私特性的借贷协议

鳄鱼视界

什么是操作系统?

Jackpop

头脑风暴:零钱兑换2

HelloWorld杰少

算法 LeetCode 8月月更

TDengine 3.0 重磅发布,首届开发者大会圆满结束

TDengine

数据库 tdengine 时序数据库

一篇就够:高性能推理引擎理论与实践(TensorRT)

AIWeker

深度学习 推理引擎 签约计划第三季 TensorRT

Android进阶(十四)Android Adapter详解

No Silver Bullet

android Adapter 8月月更

明年 Flyme 就上车?魅族与星纪时代战略合作后,携手发力出行领域

极客天地

【算法岗必看系列】机器学习高频面试题

码农鬼仔

人工智能 机器学习算法 机器学习笔记 机器学习/深度学习 常见面试题

介绍一个python工程师必须掌握的 CentOS 命令,nohup

梦想橡皮擦

Python 爬虫 8月月更

Java参数传递到底是按 值传递 还是 引用传递 ?

史俊锋在搬砖

Java 后端 编程基础 签约计划第三季

相辅相成!沈子瑜掌舵魅族科技,互相协同迈入多终端互联生态

极客天地

Kruise Rollout:灵活可插拔的渐进式发布框架

阿里巴巴云原生

阿里云 开源 云原生 OpenKruise

小菜鸟河北联通上岗培训随笔

乌龟哥哥

8月月更

物联网数据正在改变世界

CnosDB

IoT 时序数据库 开源社区 CnosDB infra

网络编程(二)TCP/IP

Albert Edison

网络编程 网络 TCP/IP 8月月更

[极致用户体验] 我做的《联机五子棋》是如何追求极致用户体验的?(上)

HullQin

CSS JavaScript html 前端 8月月更

IntelliJ IDEA 打开近期工作的项目的对话框的快捷键

HoneyMoose

Java 中使用 public,private 和 protected 修饰的方法

HoneyMoose

大佬,还记得设计模式的六大设计原则吗?

知识浅谈

设计原则 8月月更

开源一夏|OpenHarmony中FA模型中应用包结构的参数

坚果

开源 OpenHarmony 8月月更

3 分钟创建 Serverless Job 定时获取新闻热搜!

阿里巴巴云原生

阿里云 Serverless 云原生

RocketMQ事务消息

急需上岸的小谢

8月月更

Redis面试总结

TimeFriends

8月月更

大融合!魅族星纪时代达成战略合作,董事长沈子瑜透露未来大动作

极客天地

MyBatis(二、基础进阶)

mybatis springmvc 8月月更

云原生(十六)| Kubernetes篇之深入RC、RS、DaemonSet、StatefulSet

Lansonli

云原生 8月月更

用第一性原理根治数字化转型雾霾:以规则的确定性应对结果的不确定性

王和全

数字化转型 软件开发技术的第一性原理 签约计划第三季

Android进阶(十三)json应用

No Silver Bullet

json android 8月月更

使用 Kitten 开发一款趣味成语接龙游戏

汪子熙

少儿编程 scratch 8月月更 kitten 成语接龙

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