网站首页 > 博客文章 正文
Optional Chaining 是 JavaScript 的一个新特性,它允许我们在尝试访问对象的属性之前检查对象是否存在。其他语言也有类似的东西,例如,C# 的 Null Conditional 操作符,与 Optional Chaining 非常类似。
JavaScript 中的长属性访问链很容易出错,因为它们中的任何一个都可能评估为null或undefined(也称为“空”值)。要在每个步骤都中检查属性是否存在,很容易搞出来一个深层嵌套结构的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 是一个或多个属性访问和函数调用的链,其中第一个以令牌?.开头”。
提案:https://github.com/tc39/proposal-optional-chaining
使用新的 Optinal Chaining 操作符,我们可以重写上述示例,如下所示:
// Still checks for errors and is much more readable. const nameLength = db?.user?.name?.length;
如果db、user或name是undefined或null会发生什么?使用 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.users和db.users [42]可能未定义。如果数据库中有这样的用户,则假定始终定义names.first.length。
可选删除(Optinal deletion)意味着可以将delete操作符与 Optinal Chain 结合使用:
// `db.user` is deleted only if `db` is defined. delete db?.user;
更多信息参阅提案的语义部分:https://github.com/tc39/proposal-optional-chaining#semantics
我自己是一名从事了多年开发的web前端老程序员,目前辞职在做自己的web前端私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的web前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我的头条号并在后台私信我:前端,即可免费获取。
原文链接:https://v8.dev/features/optional-chaining
猜你喜欢
- 2024-11-08 Xlookup、Vlookup请走开,Wlookup函数来了
- 2024-11-08 Java 设计模式 Monads 的美丽世界
- 2024-11-08 没用 Java 8,怎么优雅地避免空指针?
- 2024-11-08 VBA|正确使用过程和自定义函数(vba 定义)
- 2024-11-08 软路由的用法(自动追剧配置)(软路由 玩法)
- 2024-11-08 Java中一致的Null值处理(java值为,到xml报错)
- 2024-11-08 java8中你可能不知道的一些地方(有关java的问题)
- 2024-11-08 Java8 Lambda使用总结(java的lambda)
- 2024-11-08 1万字详解 python logging日志模块
- 2024-11-08 看完就会用的C++17特性总结(c++ 14新特性总结)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)