JS 可选链的三种形势及好处介绍

这篇文章主要为大家介绍了JS 可选链的三种形势及好处详解,有需要的朋友可以借鉴参考下,希望能够有所帮助。

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

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

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

问题

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

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

  • 获取远程JSON数据
  • 使用配置对象
  • 有可选属性

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

// 嵌套版本

const bigObject = {

  // ...

  prop1: {

    //...

    prop2: {

      // ...

      value: 'Some value'

    }

  }

};

// 简单版本

const bigObject = {

  // ...

  prop1: {

    // Nothing here  

  }

};

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

1

2

3

4

5

if (bigObject &&

    bigObject.prop1 != null &&

    bigObject.prop1.prop2 != null) {

  let result = bigObject.prop1.prop2.value;

}

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

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

2. 易于深入访问属性

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

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

1

2

3

4

5

6

7

8

const movieSmall = {

  title: 'Heat'

};

const movieFull = {

  title: 'Blade Runner',

  director: { name: 'Ridley Scott' },

  actors: [{ name: 'Harrison Ford' }, { name: 'Rutger Hauer' }]

};

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

1

2

3

4

5

6

7

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

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

1

2

3

4

5

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

简单地说,代码片段:

1

let name = movie.director?.name;

等价于

1

2

3

4

let name;

if (movie.director != null) {

  name = movie.director.name;

}

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

2.1 数组项

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

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

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

1

2

3

4

5

6

7

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

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

1

2

3

4

5

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,则默认值为指定的值。

1

2

3

4

const noValue = undefined;

const value = 'Hello';

noValue ?? 'Nothing'; // => 'Nothing'

value   ?? 'Nothing'; // => 'Hello'

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

1

2

3

4

5

function getLeadingActor(movie) {

  return movie.actors?.[0]?.name ?? 'Unknown actor';

}

getLeadingActor(movieSmall); // => 'Unknown actor'

getLeadingActor(movieFull);  // => 'Harrison Ford'

4. 可选链的三种形式

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

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

1

2

const object = null;

object?.property; // => undefined

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

1

2

3

4

5

6

7

// 其一

const object = null;

const name = 'property';

object?.[name]; // => undefined

// 其二

const array = null;

array?.[0]; // => undefined

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

1

2

const object = null;

object?.method('Some value'); // => undefined

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

1

const value = object.maybeUndefinedProp?.maybeNull()?.[propName];

5.短路:遇到 null/undefined 停止

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

看看例子:

1

2

3

4

const nothing = null;

let index = 0;

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

index;              // => 0

6. 何时使用可选链

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

6.1访问潜在无效的属性

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

1

2

3

4

5

6

7

8

9

10

11

12

// 好

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可选属性。

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

1

2

3

4

5

6

7

8

9

10

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对象默认为零值

1

2

3

4

5

6

7

8

9

10

11

12

13

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

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

来源:微点阅读  https://www.weidianyuedu.com

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值