ES新提案:双问号操作符
摘要: 简单实用的新特性。
- 原文:ES新提案:双问号操作符
- 译者:前端小智
本文主要讲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)']
);
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新提案:双问号操作符的更多相关文章
- C#中双问号、双冒号等几个特殊关键字
1.@ 这个东东看似和邮件有关啊,但是在C#的世界里,可跟邮件没有一毛钱关系,它是string的女朋友(当然了string有N多女友),二者结合就可以发挥作用了.你可以给它起个名字,叫做“逐字字符串” ...
- C#中单问号,双问号的用法(转)
原文:http://hi.baidu.com/guodong828/blog/item/c78fc23f847314cb7d1e7193.html 单问号---用于给变量设初值的时候,给变量(int类 ...
- php两个问号??表示什么意思,PHP两个问号运算符,双问号表达式
有同学给子恒老师留言, 说在php源代码中看到有两个问号?? 不知道是什么意思. 其实两个问题??是php7新推出的表达式, c = a ?? b; 表示如果a非空,则c = a, 如果a为空,则 c ...
- Java 8 Lambda表达式之方法引用 ::双冒号操作符
双冒号运算符就是java中的方法引用,方法引用的格式是类名::方法名. 这里只是方法名,方法名的后面没有括号“()”.--------> 这样的式子并不代表一定会调用这个方法.这种式子一般是用作 ...
- c#的问号?和双问号??
1.问号?表示该变量可以为空 int? a=new int?(); Console.Writeline(a);//a是null 等价于: int? a=null; 也等价于下面这行,表示该变量默认为n ...
- C#单问号(?)与双问号(??)
1.单问号(?) 1.1 单问号运算符可以表示:可为Null类型,C#2.0里面实现了Nullable数据类型 //A.比如下面一句,直接定义int为null是错误的,错误提示为无法将null转化成i ...
- java :: Java中的双冒号操作符
java中的双冒号操作符 定义 双冒号运算操作符是类方法的句柄,lambda表达式的一种简写,这种简写的学名叫eta-conversion或者叫η-conversion. 通常的情况下: 把 x -& ...
- 蒲公英 · JELLY技术周刊 Vol.30: 此路不通?Vue 3 新提案 Ref-sugar
蒲公英 · JELLY技术周刊 Vol.30 随着 Vue 3 发布,相关的新闻也逐渐火热起来,而近期 RFC 中两个新的提案也因为某乎上的一些事情变得广为人关注.Ref sugar和script s ...
- C#中单问号(?)和双问号(??)的用法整理
1.单问号(?) 1.1 表示Nullable类型 C#2.0里面实现了Nullable数据类型 //A.比如下面一句,直接定义int为null是错误的,错误提示为无法将null转化成int,因为后者 ...
随机推荐
- 配置linux 防火墙,只有固定IP和端口才能能访问完美解决
//添加开放的端口和固定ip vi /etc/sysconfig/iptables [root@root220156 /]# echo "unset MAILCHECK"> ...
- 从零开始的SpringBoot项目搭建
前言 今天是我加入博客园的第一天今天刚好学习到SpringBoot,就顺便记录一下吧 一.创建项目 1.创建工程 ① 通过File > New > Project,新建工程,选择Sprin ...
- [20191101]完善vim的bccalc插件8.txt
[20191101]完善vim的bccalc插件8.txt --//今天移植bccalc插件到linux,发现一些问题.我自己已经在windows下使用一段时间,从来没有在linux下测试.看来很少人 ...
- 微信小程序之上传图片和图片预览
这几天一直负责做微信小程序这一块,也可以说是边做边学习吧,把自己做的微信小程序的一些功能分享出来,与大家探讨一下,相互学习相互进步. 先看下效果图 只写了一下效果样式的话希望大家不要太在意,下面马路杀 ...
- cookies和sessions组件
目录 cookie与session cookie介绍 session介绍 token django操作cookie 设置cookie 获取cookie 删除cookie 基于cookie实现的登录认证 ...
- 201871010114-李岩松《面向对象程序设计(java)》第十四周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- python直接赋值、浅拷贝、深拷贝的区别
一:直接赋值 赋值,就是对象的引用,给对象起别名. i = 8j = iprint("值是:",i, "地址:",id(i))print("值是:&q ...
- linux 软件包的组成部分
软件包的组成部分 1. 二进制文件 比如:/bin, /sbin & /usr/bin, /usr/sbin & /usr/local/bin, /usr/local/sbin 2.库 ...
- 03. Go 语言容器
Go语言容器(container) 变量在一定程度上能满足函数及代码要求.如果编写一些复杂算法.结构和逻辑,就需要更复杂的类型来实现.这类复杂类型一般情况下具有各种形式的存储和处理数据的功能,将它们称 ...
- Go 循环 (for)
循环类型 for: for a := 0; a < 10; a ++{ fmt.Println(a) } 在执行结束后 a == 10 while: a := 0 for a < 10{ ...