2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

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

评论

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

什么是隧道代理、http代理,隧道代理较于http代理有什么优势?

巨量HTTP

代理IP http代理

探索以太坊 Layer 2 解决方案的后起之秀——Starknet

Footprint Analytics

区块链 以太坊 Layer 2

国庆机酒预订又快又便宜?内附华为Mate60负一屏抢购攻略

最新动态

慢SQL治理实践及落地成果分享 | 京东物流技术团队

京东科技开发者

数据库 sql 慢SQL 企业号9月PK榜

选择渲染农场的几个标准

Finovy Cloud

游戏制作 影视制作 渲染 云渲染 渲染农场

快手发布文生图大模型“可图”,探索AI新玩法

Geek老T

短视频 AIGC

Rocketmq并发和顺序消费的失败重试机制

石臻臻的杂货铺

RocketMQ

行云管家支持信创吗?是真的吗?

行云管家

信创 国产化 行云管家

百度智能云引领建设智能云标准生态,第十二届云计算标准和应用大会成功召开

Baidu AICLOUD

智能云 大模型 AI 原生云

文心一言 VS 讯飞星火 VS chatgpt (96)-- 算法导论9.3 1题

福大大架构师每日一题

福大大架构师每日一题

市面上支持信创的堡垒机哪家好?为什么?

行云管家

网络安全 信创 数据安全 堡垒机

聚焦企业开放OpenAPI痛难点,华为云API Explorer助力构建API门户

华为云开发者联盟

软件开发 华为云 华为云开发者联盟 企业号9月PK榜

专业级PDF编辑和管理 Acrobat Pro DC 2023 for Mac

胖墩儿不胖y

Mac软件 pdf编辑器 编辑pdf pdf工具

Web3.0时代的全新合作模式:DAO | 京东云技术团队

京东科技开发者

区块链 DAO Web3.0 企业号9月PK榜

FIL NEW算力挖矿系统开发

l8l259l3365

对线面试官 - Java基础面试题【一】

派大星

Java 面试题

主动写入流对@ResponseBody注解的影响 | 京东云技术团队

京东科技开发者

spring 注解 企业号9月PK榜 @ResponseBody

termius使用ssh教程 【XShell的神器Termius】

南屿

SSH Termius

如何提高技术领导力?与你分享 5 个心得

LigaAI

程序人生 技术管理 成长与思考 技术领导力 企业号9月PK榜

中国广核集团智慧司库系统票据业务成功上线!打造票据数智管理新标杆!

用友BIP

全球司库

教你用API插件开发一个AI快速处理图片小助手

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号9月PK榜

数字化转型与架构-架构设计篇|什么是架构风格和架构模式?

数字随行

数字化转型

软通咨询杨念农:咨询2.0是企业数字化转型的大脑

软通咨询

数字化转型 #人工智能 管理咨询 数字化转型咨询

fastposter 新版本 v2.17.0 强势发布!让海报开发更简单

物有本末

图片处理 海报生成器 海报生成 海报小程序

未来AI领域的颠覆性力量

百度开发者中心

自然语言 #人工智能 文心一言

中国机械总院张红新:强化集团级数据治理 业财融合助力企业降本增效

用友BIP

2023全球商业创新大会

JDK8升级JDK11最全实践干货来了 | 京东云技术团队

京东科技开发者

Java jdk8 JDK11 企业号9月PK榜

百度集团副总裁吴甜:大语言模型面临三大技术挑战

飞桨PaddlePaddle

文心一言 文心大模型

修旧利废,提升净资产收益率

用友BIP

资产管理

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