ES新提案:双问号操作符

更新日期: 2019-07-27阅读: 2.4k标签: 操作符

本文主要讲Gabriel Isenberg撰写的ES提案“Nullish coalescing for JavaScript”。 它提出?? 替换||的运算符,并提供默认值。这里先把这相提案叫作双问号操作符


1.概述

双问号 ?? 的操作符跟 || 类似,如果给定变量值为 null 或者 undefined,刚使用双问号后的默认值,否则使用该变量值。

如下:

> undefined ?? 'default'
'default'
> null ?? 'default'
'default'
> false ?? 'default'
false
> '' ?? 'default'
''
> 0 ?? 'default'
0


2.早期的 || 运算符号

直接来个例子来演示一下 || 运算,下面两个等式是等价的:

a || b
a ? a : b

如果 a 是 truthy 值,则返回 a, 否则返回 b。

这使得使用||指定一个默认值成为可能,如果实际值是假的,那么将使用这个默认值:

const result = actualValue || defaultValue;
function getTitle(fileDesc) {
  return fileDesc.title || '(Untitled)';
}
const files = [
  {path: 'index.html', title: 'Home'},
  {path: 'tmp.html'},
];
assert.deepEqual(
  files.map(f => getTitle(f)),
  ['Home', '(Untitled)']);

请注意,基本只有在实际值undefined或为null时才应使用默认值,这是有效的,因为undefined和null都是假(虚值)的:

> undefined || 'default'
'default'
> null || 'default'
'default'

遗憾的是,如果实际值是其他的虚值,也会使用默认值:

> false || 'default'
'default'
> '' || 'default'
'default'
> 0 || 'default'
'default'

因此,这个getTitle()并不总能正常工作:

assert.equal(
  getTitle({path: 'empty.html', title: ''}),
  '(Untitled)');


3.使用双问号操作符来解决 || 运算的问题

?? 主要是用来解决 || 操作符号的一些问题,以下两个表达式是等价的:

a ?? b
a !== undefined && a !== null ? a : b

默认值是这样提供的:

const result = actualValue ?? defaultValue;

对于undefined和null, ??操作符的工作原理与||操作符相同

> undefined ?? 'default'
'default'
> null ?? 'default'
'default'

除了 undefined 和 null的其它虚值,?? 不会返回默认值。

> false ?? 'default'
false
> '' ?? 'default'
''
> 0 ?? 'default'
0

使用 ?? 来重写 getTitle():

function getTitle(fileDesc) {
  return fileDesc.title ?? '(Untitled)';
}

现在使用fileDesc调用它,它的.title是空字符串,仍然可以按符合咱们的预期工作:

assert.equal(
  getTitle({path: 'empty.html', title: ''}),
  '');

3.1 通过解构给定默认值

除了使用 ?? 给getTitle添加默认值,咱们也可以通过解构方式来给定默认值:

function getTitle({title = '(Untitled)'}) {
  return title;
}

3.2 使用 ?? 操作符号的实际例子

作为一个现实的例子,咱们使用??来简化下面的函数

function countMatches(regex, str) {
  if (!regex.global) {
    throw new Error('Regular expression must have flag /g: ' + regex);
  }
  const matchResult = str.match(regex); // null or Array
  if (matchResult === null) {
    return 0;
  } else {
    return matchResult.length;
  }
}

assert.equal(
  countMatches(/a/g, 'ababa'), 3);
assert.equal(
  countMatches(/b/g, 'ababa'), 2);
assert.equal(
  countMatches(/x/g, 'ababa'), 0);

// Flag /g is missing
assert.throws(
  () => countMatches(/a/, 'ababa'), Error);

使用 ?? 操作符号后,简化如下:

function countMatches(regex, str) {
  if (!regex.global) {
    throw new Error('Regular expression must have flag /g: ' + regex);
  }
  return (str.match(regex) ?? []).length;
}

3.3 双问号(??)操作符与可选链(?)

双问号(??)的提出是为了补充可选链(?),来看看这两兄弟结合使用的场景(第A行):

const persons = [
  {
    surname: 'Zoe',
    address: {
      street: {
        name: 'Sesame Street',
        number: '123',
      },
    },
  },
  {
    surname: 'Mariner',
  },
  {
    surname: 'Carmen',
    address: {
    },
  },
];

const streetNames = persons.map(
  p => p.address?.street?.name ?? '(no name)'); // (A)
assert.deepEqual(
  streetNames, ['Sesame Street', '(no name)', '(no name)']
);

原文:https://2ality.com/2019/08/nullish-coalescing.html

链接: https://fly63.com/article/detial/4960

js操作符拾遗

对于js操作符的一些特性和有趣题目的整理。逗号操作符有两个作用,一个是用于当你想要在期望一个表达式的位置包含多个表达式时,可以使用逗号操作符。

JavaScript剩余操作符Rest Operator

剩余操作符和展开操作符的表示方式一样,都是三个点 \\\'...\\\',但是他们的使用场景会不同。定义函数的时候,如果函数的参数以… 为前缀,则改参数是剩余参数(rest parameter)。剩余参数表示参数个数不确定的参数列表

ES6 展开操作符的几个妙用

ES6 新增了...操作符,通常用于在函数中提取剩余参数和展开数组。但其实它的用途不止于此,本文就介绍几个技巧,用它来操作 JavaScript 对象。复制对象的同时,为其添加新的属性。例子中复制了user对象到userWithPass,并添加了 password 属性。

delete操作符

delete操作符用于删除对象的某个属性;如果没有指向这个属性的引用,那它最终会被释放。对于所有情况都是true,除非属性是一个自己不可配置的属性,在这种情况下

TypeScript typeof 操作符

在 TypeScript 中, typeof 操作符可以用来获取一个变量或对象的类型。在上面代码中,我们通过 typeof 操作符获取 sem 变量的类型并赋值给 Sem 类型变量,之后我们就可以使用 Sem 类型

JS 中强大的操作符

JS 里的操作符大家每天都在使用,还有一些 ES2020、ES2021 新加的实用操作符,这些共同构成了 JS 灵活的语法生态。本文除介绍常用的操作符之外

Js中经常被忽略的两个神奇操作符?. 和 ??

?.和??估计是Javascript两个最为有用并且最经常被忽略的操作符了。这两个操作符最大的作用,就是对于undefined和null的应对,在没有lodash等库的情况下,直接桶过Javascript自身的机制就可以很大的程度上提高程序的健壮性。

一文读懂TS in操作符

上述代码规定 staffCount 是一个对象,属性名为 roles 约束的三个,值为 number 类型:类型变量 k,以此绑定到对象的每一个属性,遍历三个字符串字面量组成的联合类型 roles,number 为每个属性的值的类型

TS typeof 操作符原来有这 5 种用途!

这是一个普通的 JavaScript 对象,在 TypeScript 中你可以使用 type 或 interface 来定义该对象的类型。有了该对象类型之后,你就可以利用 TypeScript 内置的工具类型

JS中鲜为人知的知识点-空值合并运算符(??)

与逻辑或操作符(||)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如0)时。见下面的例子。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!