今天我们来介绍一个你可能没见过的 JS 新特性, 目前处于 Stage 3 阶段, 它叫作 可选链 (optional chaining), 它可能解决很多人都面对过的痛点, 让我们来了解这下~
为什么我们需要它
想象一下你从某个 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;
上面的代码很容易产生错误, 我们一般会这么改进:
- // Checking if firstName exists
- if( person &&
- person.details &&
- person.details.name ) {
- const personFirstName = person.details.name.firstName || 'stranger';
- }
Web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法
(从零基础开始到前端项目实战教程, 学习工具, 职业规划 )
可以看到为了访问某个人的 firstName, 代码变得非常不优雅. 我们可以用 lodash 来优化一下:
_.get(person, 'details.name.firstName', 'stranger');
lodash 的写法可读性更高, 但是需要引入额外的依赖, 而且在团队内部大家可能不会统一都这么写, 那么有没有更好的办法呢?
解决方案
可选链 就是为了解决这个问题而诞生的.
用法
可选链在语法上可能看起来比较陌生, 但是用了几次之后你就会很容易适应这种写法.
const personFirstName = person?.details?.name?.firstName;
其实就是在属性访问符 . 的前面加了个问号. 我们看上面语句中第一个 ?. , 从 JS 层面, 它表示如果 person 的值为 null 或者 undefined, 就不会报错而返回 undefined, 否则才继续访问后面的 details 属性. 而如果后面的属性访问链中有任何一个属性为 null 或者 undefined, 那么最终的值就为 undefined.
默认值
为了优雅地设置默认值, 我们引入另外一个特性: 空值合并运算符 (nullish-coalescing-operator), 听起来好像很复杂, 其实也很简单:
const personFirstName = person?.details?.name?.firstName ?? 'stranger';
这个运算符就是 ??, 如果它左侧表达式的结果是 undefined,personFirstName, 就会取右侧的 stranger.
是不是跟短路运算符 || 很像, 那假如我们把 ?? 换成 || 呢?
上面的例子中, 如果 firstName 的值为 0 或者空字符串等非 undefined 的 falsy 值, 那么最终的结果就不一样了.
?? 就是为了取代 || , 来做设置默认值这件事的.
动态属性
如果你需要使用动态属性, 同样很简单:
- const jobNumber = 1;
- const secondJob = person?.jobs?.[jobNumber] ?? 'none';
上面的代码中, jobs?.[jobNumber] 和 jobs[jobNumber] 的含义是一样的, 区别就是前者不会报错.
函数或方法调用
同样的, 如果想安全调用一个方法, 只需要使用 ?.():
const currentJob = person?.jobs.getCurrentJob?.() ?? 'none';
Web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法
(从零基础开始到前端项目实战教程, 学习工具, 职业规划 )
如果 getCurrentJob 不是一个函数, currentJob 的值就是 none
现在就使用这个特性
很显然, 这个特性的兼容性感人, 不过没关系, 我们有 babel!
立刻, 马上就能让你使用它: babel-plugin-proposal-optional-chaining
最后的话
这个特性在很多其他的语言如 C#,Swift 中都有实现, 并且 TypeScript 中也已经加入该特性. 感兴趣的小伙伴还不快尝试一下, 如果嫌安装 babel plugin 太麻烦, 直接使用 lodash 的 get 也不失为一种保守的选择~
来源: http://www.jianshu.com/p/47e1785c8648