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、微脉、青团社等众多品牌企业。欢迎大家免费试用!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Tendermint JSONRPC API中文手册
Tendermint RPC API文档中文版由汇智网翻译整理,访问地址:http://cw.hubwiz.com/card/c/tendermint-rpc-api/。 配置:可以使用配置文件 $TMHOME/config/config.toml或使用命令行参数--rpc.X 来调整terdernmint节点的rpc功能。 监听地址:默认的rpc监听地址是tcp://0.0.0.0:26657,要设置为其他地址,可以修改laddr配置参数。 CORS:要启用CORS,可以配置以下参数: cors_allowed_origins cors_allowed_methods cors_allowed_headers 字符串参数:RPC API的调用参数如果要求是字符串或字节数组,那么可以传入带引号的字符串,例如"abc"或者0x前缀的16进制表示,例如0x616263。 POST请求:JSONRPC请求可以采用HTTP协议的POST方式发送到RPC根访问点,即:http://localhost:26657/。 WebSocket请求:JSONRPC请求可以使用websocket通道。Ten...
- 下一篇
基于MyBatis注解扩展,实现无需配置就可拥有增删改
一、使用篇 如果项目本身基于SpringMVC+Mybatis构建,不需添加任何配置Mapper类只需继承 BaseMapper,即拥有增删改方法操作,无需任何配置文件 package com.springmvc.mapper; import org.springframework.stereotype.Repository; import com.nmtx.mybatis.ext.mapper.BaseMapper; import com.springmvc.model.User; @Repository public interface UserMapper extends BaseMapper<User>{ } package com.springmvc.service.impl; import javax.annotation.Resource; import org.springframework.stereotype.Service; import com.springmvc.mapper.UserMapper; import com.springmvc....
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- 设置Eclipse缩进为4个空格,增强代码规范
- Mario游戏-低调大师作品
- MySQL8.0.19开启GTID主从同步CentOS8
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16