资讯专栏INFORMATION COLUMN

JS 可选链的好处

habren / 1563人阅读

摘要:到年月,一个新的可选链提案已经进入第三阶段,这是一个很好的改进。可选链接改变了从深层对象结构访问属性的方式。咱们来看看可选链如何解决这个问题,以减少冗余的代码。该对象包含必填属性,以及可选的和。可选链运算符可防止抛出。

为了保证的可读性,本文采用意译而非直译。

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!

JS的一些特性极大地改变了咱们的编码方式。从ES6年开始,对咱们代码影响最大的特性的解 、箭头函数、类和模块系统。

到2019年8月,一个新的可选链提案已经进入第三阶段,这是一个很好的改进。可选链接改变了从深层对象结构访问属性的方式。

来看看这是又是什么骚操作。

这个礼拜《大迁世界》有抽奖活动,奖品:专栏 《左耳听风》 x3, 技术书 x5,欢迎关注回复:抽奖
问题

由于JS的动态特性,对象可以具有多层不同的嵌套对象结构。

通常,当咱们处理以下这些对象时:

获取远程JSON数据

使用配置对象

有可选属性

虽然JS为对象支持不同层次数据结构,但是在访问此类对象的属性时,复杂性也随着增加。

bigObject可以在运行时拥有不同的属性集

// 嵌套版本
const bigObject = {
  // ...
  prop1: {
    //...
    prop2: {
      // ...
      value: "Some value"
    }
  }
};

// 简单版本
const bigObject = {
  // ...
  prop1: {
    // Nothing here   
  }
};

因此,必须手动检查属性是否存在

if (bigObject && 
    bigObject.prop1 != null && 
    bigObject.prop1.prop2 != null) {
  let result = bigObject.prop1.prop2.value;
}

这样写太过冗长了,最好避免写它。

咱们来看看可选链如何解决这个问题,以减少冗余的代码。

2. 易于深入访问属性

设计一个保存电影信息的对象。 该对象包含必填title属性,以及可选的directoractors

movieSmall对象仅包含title,而movieFull包含完整的属性集:

const movieSmall = {
  title: "Heat"
};

const movieFull = {
  title: "Blade Runner",
  director: { name: "Ridley Scott" },
  actors: [{ name: "Harrison Ford" }, { name: "Rutger Hauer" }]
};

写一个获取director的函数。 请记住,director 可能不存在。

function getDirector(movie) {
  if (movie.director != null) {
    return movie.director.name;
  }
}

getDirector(movieSmall); // => undefined
getDirector(movieFull);  // => "Ridley Scott"

if(movie.director){...}条件用于验证是否定义了director属性。 如果没有这个预防措施,在访问movieSmall对象的director时,JS会抛出TypeError: Cannot read property "name" of undefined

这种场景最适合使用可选链的功能了,如下所示,代码将简洁很多。

function getDirector(movie) {
  return movie.director?.name;
}

getDirector(movieSmall); // => undefined
getDirector(movieFull);  // => "Ridley Scott"

在movie.director?.name表达式中可以找到?.可选的链接操作符。

movieSmall中,没有director属性。 因此,movie.director?.name的的结果为undefined。 可选链运算符可防止抛出 TypeError: Cannot read property "name" of undefined

简单地说,代码片段:

let name = movie.director?.name;

等价于

let name;
if (movie.director != null) {
  name = movie.director.name;
}

?.通过减少两行代码简化getDirector()函数,这就是为什么我喜欢可选链的原因。

2.1 数组项

可选的链功能可以做得更多。可以自由地在同一个表达式中使用多个可选的链接操作符,甚至可以使用它安全地访问数组项。

下一个任务是编写一个函数,返回电影的actors中的name

movie对象中,actors数组可以是空的,甚至是缺失的,因此必须添加额外的条件来判空。

function getLeadingActor(movie) {
  if (movie.actors && movie.actors.length > 0) {
    return movie.actors[0].name;
  }
}

getLeadingActor(movieSmall); // => undefined
getLeadingActor(movieFull);  // => "Harrison Ford"

if (movie.actors && movies.actors.length > 0) {...}条件主要判断movie包含actors属性,并且此属性至少有一个actor

使用可选链接,同样代码也简洁了很了,如下:

function getLeadingActor(movie) {
  return movie.actors?.[0]?.name;
}

getLeadingActor(movieSmall); // => undefined
getLeadingActor(movieFull);  // => "Harrison Ford"

actors?. 确保actors属性存在, [0]?.确保列表中存在第一个actor

3.双问号操作符

一个名为nullish coalescing operator的新提议? 处理undefinednull,将它们默认为特定值。

表达式变量?? 如果变量undefined或为null,则默认值为指定的值。

const noValue = undefined;
const value = "Hello";

noValue ?? "Nothing"; // => "Nothing"
value   ?? "Nothing"; // => "Hello"

接着使用??来优化一下 getLeading()函数,当movie对象中没有actor时返回“Unknown actor

function getLeadingActor(movie) {
  return movie.actors?.[0]?.name ?? "Unknown actor";
}

getLeadingActor(movieSmall); // => "Unknown actor"
getLeadingActor(movieFull);  // => "Harrison Ford"

4. 可选链的三种形式

咱们可以使用以下3种形式的可选链。

第一种: object?.property 用于访问静态属性:

const object = null;
object?.property; // => undefined

第二种:object?.[expression] 用于访问动态属性或数组项:

// 其一
const object = null;
const name = "property";
object?.[name]; // => undefined
// 其二
const array = null;
array?.[0]; // => undefined

第三种:object?.([arg1, [arg2, ...]]) 执行一个对象方法

const object = null;
object?.method("Some value"); // => undefined

将这三种组合起来创建一个可选链:

const value = object.maybeUndefinedProp?.maybeNull()?.[propName];
5.短路:遇到 null/undefined 停止

可选链接运算符的有趣之处在于,只要在左侧leftHandSide?.rightHandSide遇到无效值,右侧访问就会停止,这称为短路。

看看例子:

const nothing = null;
let index = 0;

nothing?.[index++]; // => undefined
index;              // => 0

6. 何时使用可选链

不要急于使用可选的链操作符来访问任何类型的属性:这会导致错误的使用。

6.1访问潜在无效的属性

?.一般使用在可能为空的属性:maybeNullish?.prop。在确定属性不为空的情况下,使用属性访问器:.property或[propExpression]

// 好
function logMovie(movie) {
  console.log(movie.director?.name);
  console.log(movie.title);
}

// 不好
function logMovie(movie) {
  // director needs optional chaining
  console.log(movie.director.name);

  // movie doesn"t need optional chaining
  console.log(movie?.title);
}
6.2 通常有更好的选择

以下函数hasPadding()接收可选padding属性的样式对象。 padding具有lefttoprightbottom可选属性。

尝试使用可选的链操作符:

function hasPadding({ padding }) {
  const top = padding?.top ?? 0;
  const right = padding?.right ?? 0;
  const bottom = padding?.bottom ?? 0;
  const left = padding?.left ?? 0;
  return left + top + right + bottom !== 0;
}

hasPadding({ color: "black" });        // => false
hasPadding({ padding: { left: 0 } });  // => false
hasPadding({ padding: { right: 10 }}); // => true

虽然函数正确地确定了元素是否有padding,但是对于每个属性使用可选的链有点过于麻烦了。

更好的方法是使用对象扩展操作符将padding对象默认为零值

function hasPadding({ padding }) {
  const p = {
    top: 0,
    right: 0,
    bottom: 0,
    left: 0,
    ...padding
  };
  return p.top + p.left + p.right + p.bottom !== 0;
}

hasPadding({ color: "black" });        // => false
hasPadding({ padding: { left: 0 } });  // => false
hasPadding({ padding: { right: 10 }}); // => true

这个就比可选链来的更简洁。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

原文:https://dmitripavlutin.com/ja...

交流

干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。

https://github.com/qq44924588...

我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!

关注公众号,后台回复福利,即可看到福利,你懂的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106986.html

相关文章

  • Nginx配置SSL后不能正常访问解决方法

    摘要:今天决定给自己的站点配置,配置完成后发现不能正常访问,思来想去发现是未开启端口。这也是不指定规则序号时的默认方式。参数给出一个合法的目标。给出当前命令语法非常简短的说明。 今天决定给自己的站点配置SSL,配置完成后发现不能正常访问,思来想去发现是未开启443端口。 Linux防火墙开放特定端口 方法一 找到/etc/sysconfig/iptables文件加入如下代码,并保存 -A I...

    CompileYouth 评论0 收藏0
  • Nginx配置SSL后不能正常访问解决方法

    摘要:今天决定给自己的站点配置,配置完成后发现不能正常访问,思来想去发现是未开启端口。这也是不指定规则序号时的默认方式。参数给出一个合法的目标。给出当前命令语法非常简短的说明。 今天决定给自己的站点配置SSL,配置完成后发现不能正常访问,思来想去发现是未开启443端口。 Linux防火墙开放特定端口 方法一 找到/etc/sysconfig/iptables文件加入如下代码,并保存 -A I...

    shinezejian 评论0 收藏0
  • Nginx配置SSL后不能正常访问解决方法

    摘要:今天决定给自己的站点配置,配置完成后发现不能正常访问,思来想去发现是未开启端口。这也是不指定规则序号时的默认方式。参数给出一个合法的目标。给出当前命令语法非常简短的说明。 今天决定给自己的站点配置SSL,配置完成后发现不能正常访问,思来想去发现是未开启443端口。 Linux防火墙开放特定端口 方法一 找到/etc/sysconfig/iptables文件加入如下代码,并保存 -A I...

    ccj659 评论0 收藏0
  • Swift 中的 7 个陷阱以及如何避免

    摘要:原文链接前言伴随着语言的快速发展,我们对于苹果设备编程的认识也发生着变化。这其中的一些陷阱在官方的书里面,但是还有一些书中并没有提及。例如苹果提供了实现的用户体验,系统工具等功能很多框架。 作者: David Ungar,时间:2016/1/27 翻译:BigNerdCoding, 如有错误欢迎指出。原文链接 前言 伴随着Swift语言的快速发展,我们对于苹果设备编程的认识也发生着变...

    sourcenode 评论0 收藏0
  • 使用 Optional Chaining 做数据防御

    摘要:如果大家阅读过我之前写的一篇关于解构的文章,那一定会了解到解构达到数据防御功能,那么本文要介绍的是另一种数据防御方式可选链。什么是允许我们检查对象是否存在,然后才试图访问它的属性。如何使用目前在阶段。 如果大家阅读过我之前写的一篇关于ES6解构的文章,那一定会了解到解构达到数据防御功能,那么本文要介绍的是另一种数据防御方式Optional Chaining(可选链)。 什么是Optio...

    zhonghanwen 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<