Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

可选链式调用和空合并 #9

Open
liujinxing opened this issue Dec 25, 2019 · 2 comments
Open

可选链式调用和空合并 #9

liujinxing opened this issue Dec 25, 2019 · 2 comments

Comments

@liujinxing
Copy link
Member

liujinxing commented Dec 25, 2019

可选链式调用和空合并

在防御性编程的要求下,我们需要时刻小心地处理着 null 和 undefined,如下面的写法:

if (x && x.y && x.y.z) {
  x.y.z();
}
const b = x || '默认值'; // 警告:本意是 x 为 null 或者 undefined 时,b = '默认值'

今天介绍两种语法糖,来简化或者正确处理 null 和 undefined:

ts-lib-scripts 的支持

需要升级 ts-lib-tools 到 0.8.3 版本才能支持。

可选链式调用

可选调用链是一个或多个属性访问和函数调用的链,以?.开头。

例子:对象属性访问

const z = x?.y?.z;

相当于:

const z = x && x.y ? x.y.z : undefined;

更严格地说相当于:

const z = x != null && x.y != null ? x.y.z : undefined;

例子:数组

比如需要获取数组x的第一个元素的y属性的z属性,而且x 可能为空或者空数组,数组元素也可能是空值:

const z = x?.[0]?.y?.z;

相当于:

const z = x && x[0] && x[0].y ? x[0].y.z : undefined;

例子:动态属性

与数组的用法一致:

const propertyName = 'y';
const z = x?.[propertyName]?.z;

相当于:

const propertyName = 'y';

const z = x && x[propertyName]? x[propertyName].z : undefined;

例子:函数调用

const result = x?.();
const z = x?.().y.z;

相当于:

const result = x != null ? x() : undefined;
const z = x != null ? x().y.z : undefined;

例子:可选删除

delete x?.y;

相当于:

if (x != null) {
    delete x.y;
}

例子:短路特性

可选链式调用的一个特性:短路特性。

let i = 0;

x?.y.z(++i);

如果 x 为空,上面的代码执行完之后, i 仍然为 0

相当于:

let i = 0;

if (x != null) {
    x.y.z(++i);
}

例子:堆叠特性

可选链式调用的第二个特性是堆叠,意思是:在可选链式调用中,可以组合使用对象属性访问、数组元素访问、函数调用,如下所示:

const e = a?.b?.[0]?.c()?.d?.e;

相当于:

const e = a != null &&
      a.b != null &&
      a.b[0] != null &&
      a.b[0].c != null &&
      a.b[0].c() != null &&
      a.b[0].c().d != null?
          a.b[0].c().d.e :
          undefined;

(注意:翻译的代码没有做优化,请大家忽略此问题。)

注意

如果确定值不为空,则没必要使用可选链式调用语法。

空合并

const y = x ?? '默认值';

相当于:

const y = x == null ? '默认值' : x;

空合并语法比 x || '默认值' 更安全。举一个不安全的用法:

let x: number | undefined | null = 0;

const y = x || 10;

本意是希望 x 为空时,y = 10,其他情况 y = x。按照意图,期望执行结果是 y = 0,但是实际上是 y = 10。正确的写法是:

let x: number | undefined | null = 0;

const y = x ?? 10;
@liujinxing
Copy link
Member Author

liujinxing commented Dec 27, 2019

列举一种错误用法:

value?.items?.indexOf('x') !== -1

正确的写法是:

value?.items?.includes('x')

如果需要严格返回布尔值,则:

value?.items?.includes('x') ?? false

对比一下原始写法:

value && value.items && value.items.includes('x');

// 更严谨的写法
!!(value && value.items && value.items.includes('x'));

@liujinxing liujinxing pinned this issue Dec 27, 2019
@liujinxing liujinxing unpinned this issue Dec 27, 2019
@liujinxing
Copy link
Member Author

对比一下写法:

方式一:

x ? x.items.map(item => item.id) : [];

方式二:

x?.items.map(item => item.id) ?? [];

方式三:

x?.items.map(item => item.id) || [];

tianyanqiu referenced this issue in sinoui/alert Jan 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant