摘要: 简单实用的新特性。

本文主要讲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时才应使用默认值,这是有效的,因为undefinednull都是假(虚值)的:

    > 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;

对于undefinednull??操作符的工作原理与||操作符相同

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

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

    > 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)']
);

4. 兼容性

可以通过ECMAScript Next compatibility table 查看 ?? 支持情况。

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

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了20亿+错误事件,付费客户有阳光保险、核桃编程、荔枝FM、掌门1对1、微脉、青团社等众多品牌企业。欢迎大家免费试用

ES新提案:双问号操作符的更多相关文章

  1. C#中双问号、双冒号等几个特殊关键字

    1.@ 这个东东看似和邮件有关啊,但是在C#的世界里,可跟邮件没有一毛钱关系,它是string的女朋友(当然了string有N多女友),二者结合就可以发挥作用了.你可以给它起个名字,叫做“逐字字符串” ...

  2. C#中单问号,双问号的用法(转)

    原文:http://hi.baidu.com/guodong828/blog/item/c78fc23f847314cb7d1e7193.html 单问号---用于给变量设初值的时候,给变量(int类 ...

  3. php两个问号??表示什么意思,PHP两个问号运算符,双问号表达式

    有同学给子恒老师留言, 说在php源代码中看到有两个问号?? 不知道是什么意思. 其实两个问题??是php7新推出的表达式, c = a ?? b; 表示如果a非空,则c = a, 如果a为空,则 c ...

  4. Java 8 Lambda表达式之方法引用 ::双冒号操作符

    双冒号运算符就是java中的方法引用,方法引用的格式是类名::方法名. 这里只是方法名,方法名的后面没有括号“()”.--------> 这样的式子并不代表一定会调用这个方法.这种式子一般是用作 ...

  5. c#的问号?和双问号??

    1.问号?表示该变量可以为空 int? a=new int?(); Console.Writeline(a);//a是null 等价于: int? a=null; 也等价于下面这行,表示该变量默认为n ...

  6. C#单问号(?)与双问号(??)

    1.单问号(?) 1.1 单问号运算符可以表示:可为Null类型,C#2.0里面实现了Nullable数据类型 //A.比如下面一句,直接定义int为null是错误的,错误提示为无法将null转化成i ...

  7. java :: Java中的双冒号操作符

    java中的双冒号操作符 定义 双冒号运算操作符是类方法的句柄,lambda表达式的一种简写,这种简写的学名叫eta-conversion或者叫η-conversion. 通常的情况下: 把 x -& ...

  8. 蒲公英 · JELLY技术周刊 Vol.30: 此路不通?Vue 3 新提案 Ref-sugar

    蒲公英 · JELLY技术周刊 Vol.30 随着 Vue 3 发布,相关的新闻也逐渐火热起来,而近期 RFC 中两个新的提案也因为某乎上的一些事情变得广为人关注.Ref sugar和script s ...

  9. C#中单问号(?)和双问号(??)的用法整理

    1.单问号(?) 1.1 表示Nullable类型 C#2.0里面实现了Nullable数据类型 //A.比如下面一句,直接定义int为null是错误的,错误提示为无法将null转化成int,因为后者 ...

随机推荐

  1. Navicat Premium12.0 常用快捷键

  2. 【C#】学习笔记 abstract、virtual、interface使用的一些栗子

  3. iOS sqlite ORM框架-LKDBHelper

    LKDBHelper 一个sqlite ORM(全自动操作数据库)框架. 线程安全.不再担心递归锁死的问题 安装要求 iOS 4.3+ 仅支持 ARC FMDB 添加到你的项目 如果你使用 Cocoa ...

  4. centos图形化桌面安装过程

    连接 1.安装xwindow yum -y groupinstall "X Window System" \\安装 X Window System 环境 2.安装gnome des ...

  5. 【解决 FTP】windows访问Linux的vsftpd(FTP服务器)问题200 Switching to ASCII mode,227 Entering Passive Mode

    转载:关于FTP主动模式(active mode)与被动模式(passive mode)的工作原理: 主动模式(服务器向客户端敲门,然后客户端开门)FTP:客户机与服务器之间建立连接时,客户机是大于1 ...

  6. juc-2-原子变量与CAS算法

      i++的原子性问题 例子   int i=10;           i++; 结果   i=10   分析过程                    在计算机 底层 会有生成一个临时变量 tem ...

  7. 定义私有指令 v-fontweight

    // 这是一个私有的指令 他是在vm这个实例对象里里面的 所以说是私有的 directives 多一个s // 在css中是font-Weight.在第二个字母的大写该为小写,去掉横线. // 这中写 ...

  8. 异常类的构建——顶层父类Exception的实现

    异常类构建异常的类型可以是自定义类类型对于类类型异常的匹配依旧是从上到下严格的匹配赋值兼容性原则在异常匹配中依然适用一般而言-匹配子类异常的catch放在上部-匹配父类异常的catch放在下部 现代C ...

  9. Codeforces Round #603 (Div. 2) C. Everyone is a Winner! 二分

    C. Everyone is a Winner! On the well-known testing system MathForces, a draw of n rating units is ar ...

  10. Codeforces Round #599 (Div. 1) A. Tile Painting 数论

    C. Tile Painting Ujan has been lazy lately, but now has decided to bring his yard to good shape. Fir ...