对于使用Javascript
的每个人来说,可选链(Optional chaining)是游戏的规则的改变者。它与箭头函数或let
和const
一样重要。我们讨论下它可以解决什么问题,它如何工作,以及它如何使得你的生活更加轻松。
问题
想象以下场景:
你正在使用片段代码来从一个API
加载数据。返回数据是深度嵌套的对象,这就意味着你需要遍历很长的对象属性。
// API response object
const person = {
details: {
name: {
firstName: "Michael",
lastName: "Lampe",
}
},
jobs: [
"Senior Full Stack Web Developer",
"Freelancer"
]
}
// Getting the firstName
const personFirstName = person.details.name.firstName;
现在,保留这样的代码也是不错的。不过,有个更好的解决方法,如下:
代码语言:javascript复制// Checking if firstName exists
if( person &&
person.details &&
person.details.name ) {
const personFirstName = person.details.name.firstName || 'stranger';
}
正如示例中你所看到的,即使是简单的事情,比如获取一个人的名字,也很难正确获取。
所以,这就是为什么我们使用类似lodash
库去处理这样的事情:
_.get(person, 'details.name.firstName', 'stranger');
lodash
使得代码更具可读性,但是你得在你的代码库中引入很多的依赖。你需要更新它,然后,如果你在一个团队中工作,你需要在团队中推广使用它。所以,这也不是一个理想的解决方案。
解决方案
可选链为这些(除了团队的问题)提供了一个解决方案。
它是怎么工作的
初次看到可选链的新语法,你可能会感到陌生,但是,几分钟后你会习惯它的。
代码语言:javascript复制const personFirstName = person?.details?.name?.firstName;
好了,现在你脑子可能有很多问号(双关语义)。上面语法的?
是个新的事物。这就是你要想想的地方了。在属性前(原文应该改为属性后比较准确)有?.
,就是在问你属性person
存在吗?或者,更加javascript
的表达方式--person
属性的值是null
或undefined
吗?如果是,将不会返回一个错误,而是返回undefined
。所以personFirstName
将返回undefined
。对details?
和name?
会进行重复的询问。如果任意一个的值为null
或undefined
,之后personFirstName
都会返回undefined
。这被称为Short-circuiting(短路)
。一旦javascript
找到值为null
或undefined
,它就会短路并不会再深入查询下去。
默认值
我们还需要学学Nullish coalescing operator(空位合并运算符)
。好吧,这听起来很难学。但是实际上,一点也不难。我们看看下面的例子:
const personFirstName = person?.details?.name?.firstName ?? 'stranger';
Nullish coalescing operator
用??
来表示。它也很容易去解读。如果??
左侧返回的内容是undefined
,那么personFirstName
会将??
右侧的值赋值给它。这太容易了。
动态属性
有时候你需要获取动态的值。它可能是一个数组的值,或者是一个对象的动态属性。
代码语言:javascript复制const jobNumber = 1;
const secondJob = person?.jobs?.[jobNumber] ?? 'none';
这里需要重点理解的地方是jobs?.[jobNumber]
,它和jobs[jobNumber]
表达的一样,但是不会抛出一个错误;相反,它会返回none
值。
函数或方法调用
有时候,你会处理对象,而你不知道它们是否带有方法。这里我们可以使用?.()
语法或带参数?.({ some: 'args'})
语法。它会根据你的需求运行。如果在那个对象中不存在这个方法,它会返回值undefined
。
const currentJob = person?.jobs.getCurrentJob?.() ?? 'none';
上面的例子中,如果没有getCurrentJob
方法,那么currentJob
将会返回none
。
今天开始使用它
目前没有浏览器支持此功能--Babel做转换了。
这里已经有一个babel.js
插件,如果你已经有了Babel
设置,那就很容易集成了。
babel-plugin-proposal-optional-chaining
参考和后话
- 原文:dev.to/lampewebdev…
- 文章首发:github.com/reng99/blog…
- 更多内容:github.com/reng99/blog…