摘要: 简单实用的新特性。html
本文主要讲Gabriel Isenberg撰写的ES提案“Nullish coalescing for JavaScript”。 它提出??
替换||
的运算符,并提供默认值。这里先把这相提案叫做双问号操做符,若是你有好的叫法,欢迎留言讨论。前端
双问号 ??
的操做符跟 ||
相似,若是给定变量值为 null
或者 undefined
,刚使用双问号后的默认值,不然使用该变量值。git
以下:github
> undefined ?? 'default' 'default' > null ?? 'default' 'default' > false ?? 'default' false > '' ?? 'default' '' > 0 ?? 'default' 0
直接来个例子来演示一下 ||
运算,下面两个等式是等价的:express
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
都是假(虚值)的:segmentfault
> undefined || 'default' 'default' > null || 'default' 'default'
遗憾的是,若是实际值是其余的虚值,也会使用默认值:微信小程序
> false || 'default' 'default' > '' || 'default' 'default' > 0 || 'default' 'default'
所以,这个getTitle()
并不总能正常工做:微信
assert.equal( getTitle({path: 'empty.html', title: ''}), '(Untitled)');
??
主要是用来解决 ||
操做符号的一些问题,如下两个表达式是等价的:
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: ''}), '');
除了使用 ??
给getTitle
添加默认值,我们也能够经过解构方式来给定默认值:
function getTitle({title = '(Untitled)'}) { return title; }
做为一个现实的例子,我们使用??
来简化下面的函数。
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; }
双问号(??
)的提出是为了补充可选链(?
),来看看这两兄弟结合使用的场景(第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)'] );
能够经过ECMAScript Next compatibility table 查看 ??
支持状况。
代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug。
Fundebug专一于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了20亿+错误事件,付费客户有阳光保险、核桃编程、荔枝FM、掌门1对一、微脉、青团社等众多品牌企业。欢迎你们免费试用!