ES2020系列之空值合并运算符 '??'


Posted in Javascript onJuly 22, 2020

空值合并运算符 ?? 提供了一种简短的语法,用来获取列表中第一个“已定义”的变量(译注:即值不是 null 或 undefined 的变量)。

a ?? b 的结果是:

  • a,如果 a 不是 null 或 undefined,
  • b,其他情况。

所以,x = a ?? b 是下面这个表达式的简写:

x = (a !== null && a !== undefined) ? a : b;

下面是一个更长一点的例子。

假设,我们有一个用户,变量 firstName、lastName 和 nickName 分别对应用户的名字、姓氏和昵称。如果用户决定不输入任何值,那么这些变量都可能是未定义的。

我们想要显示用户的名称:显示这三个变量中的一个,如果都没有设置值,则显示 "Anonymous"。
让我们使用 ?? 运算符选择第一个已定义的变量:

let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// 显示第一个不是 null/undefined 的值
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder

与 || 比较

或运算符 || 可以与 ?? 运算符以同样的方式使用。正如 上一章 所讲的,我们可以用 || 替换上面示例中的 ??,也可以获得相同的结果。

重要的区别是:

  • || 返回第一个 真 值。
  • ?? 返回第一个 已定义的 值。

当我们想将 null/undefined 与 0 区别对待时,这个区别至关重要。

例如,考虑下面这种情况:

height = height ?? 100;

如果 height 未定义,则将其赋值为 100。

让我们将其与 || 进行比较:

let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0

在这个例子中,height || 100 将值为 0 的 height 视为未设置的(unset),与 null、undefined 以及任何其他假(falsy)值同等对待。因此得到的结果是 100。

height ?? 100 仅当 height 确实是 null 或 undefined 时才返回 100。因此,alert 按原样显示了 height 值 0。

哪种行为更好取决于特定的使用场景。当高度 0 为有效值时,?? 运算符更适合。

优先级

?? 运算符的优先级相当低:在 MDN table 中为 5。

因此,?? 在大多数其他运算之后,但在 = 和 ? 之前进行运算。

如果我们需要在复杂表达式中使用 ?? 进行取值,需要考虑加括号:

let height = null;
let width = null;

// 重要:使用括号
let area = (height ?? 100) * (width ?? 50);

alert(area); // 5000

否则,如果我们省略了括号,* 的优先级比 ?? 高,会优先执行。

运算过程将等同于下面这个表达式:

// 可能不正确的
let area = height ?? (100 * width) ?? 50;

这里还有一个相关的语言级别的限制。

出于安全原因,禁止将 ?? 运算符与 && 和 || 运算符一起使用。

下面的代码会触发一个语法错误:

let x = 1 && 2 ?? 3; // Syntax error

这个限制无疑是值得商榷的,但是它被添加到语言规范中是为了避免编程错误,因为人们开始使用 ?? 替代 ||。

可以明确地使用括号来解决这个问题:

let x = (1 && 2) ?? 3; // 起作用

alert(x); // 2

总结

空值合并运算符 ?? 提供了一种简洁的方式获取列表中“已定义”的值。

它被用于为变量分配默认值:

// 当 height 的值为 null 或 undefined 时,将 height 的值设置为 100
height = height ?? 100;

?? 运算符的优先级非常低,只略高于 ? 和 =。

如果没有明确添加括号,不能将其与 || 或 && 一起使用。

到此这篇关于ES2020系列之空值合并运算符 '??'的文章就介绍到这了,更多相关ES2020 空值合并运算符 内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
与jquery serializeArray()一起使用的函数,主要来方便提交表单
Jan 31 Javascript
javascript 获取HTML DOM父、子、临近节点
Jun 16 Javascript
JS实现选中当前菜单后高亮显示的导航条效果
Oct 15 Javascript
jQuery+CSS3实现3D立方体旋转效果
Nov 10 Javascript
基于jquery步骤进度条源码分享
Nov 12 Javascript
JavaScript数据类型学习笔记
Jan 25 Javascript
jquery实现全选功能效果的实现代码
May 05 Javascript
js中数组的常用方法小结
Dec 30 Javascript
用js屏蔽被http劫持的浮动广告实现方法
Aug 10 Javascript
微信小程序实现顶部下拉菜单栏
Nov 04 Javascript
解决layui追加或者动态修改的表单元素“没效果”的问题
Sep 18 Javascript
vue实现简单计算商品价格
Sep 14 Javascript
解决vue单页面 回退页面 keeplive 缓存问题
Jul 22 #Javascript
vue移动端弹起蒙层滑动禁止底部滑动操作
Jul 22 #Javascript
在vue中实现禁止屏幕滚动,禁止屏幕滑动
Jul 22 #Javascript
vue 弹出遮罩层样式实例
Jul 22 #Javascript
vue中解决拖拽改变存在iframe的div大小时卡顿问题
Jul 22 #Javascript
vue中实现拖动调整左右两侧div的宽度的示例代码
Jul 22 #Javascript
在vue中实现禁止回退上一步,路由不存历史记录
Jul 22 #Javascript
You might like
坏狼的PHP学习教程之第2天
2008/06/15 PHP
PHP采用XML-RPC构造Web Service实例教程
2014/07/16 PHP
mysql_connect localhost和127.0.0.1的区别(网络层阐述)
2015/03/26 PHP
禁止直接访问php文件代码分享
2020/05/05 PHP
分享几种好用的PHP自定义加密函数(可逆/不可逆)
2020/09/15 PHP
js技巧--转义符"\"的妙用
2007/01/09 Javascript
jQuery动态添加、删除元素的方法
2014/01/09 Javascript
推荐一个自己用的封装好的javascript插件
2015/01/29 Javascript
JavaScript正则表达式实例详解
2016/10/16 Javascript
BootStrap框架个人总结(bootstrap框架、导航条、下拉菜单、轮播广告carousel、栅格系统布局、标签页tabs、模态框、菜单定位)
2016/12/01 Javascript
js仿京东轮播效果 选项卡套选项卡使用
2017/01/12 Javascript
jQuery实现百度登录框的动态切换效果
2017/04/21 jQuery
js循环map 获取所有的key和value的实现代码(json)
2018/05/09 Javascript
详解nodejs解压版安装和配置(带有搭建前端项目脚手架)
2018/12/06 NodeJs
JS apply用法总结和使用场景实例分析
2020/03/14 Javascript
基于JavaScript实现表格隔行换色
2020/05/08 Javascript
[04:54]DOTA2 2017国际邀请赛:上届冠军WINGS采访短片
2017/08/09 DOTA
[01:01:42]Secret vs Optic Supermajor 胜者组 BO3 第二场 6.4
2018/06/05 DOTA
跨平台python异步回调机制实现和使用方法
2013/11/26 Python
Python虚拟环境项目实例
2017/11/20 Python
Python格式化输出%s和%d
2018/05/07 Python
使用 Python 实现微信群友统计器的思路详解
2018/09/26 Python
python实现浪漫的烟花秀
2019/01/30 Python
python中的decimal类型转换实例详解
2019/06/26 Python
一款纯css3实现的漂亮的404页面的实例教程
2014/11/27 HTML / CSS
墨西哥运动服饰和鞋网上商店:Netshoes墨西哥
2016/07/28 全球购物
美国网上花店:JustFlowers
2017/02/12 全球购物
凯伦·米莲女装网上商店:Karen Millen
2017/11/07 全球购物
安德玛比利时官网:Under Armour比利时
2019/08/28 全球购物
以太网Ethernet IEEE802.3
2013/08/05 面试题
学期自我鉴定范文
2013/10/01 职场文书
企业管理部经理岗位职责
2013/12/24 职场文书
农林环境专业求职信
2014/03/13 职场文书
沈阳故宫导游词
2015/01/31 职场文书
女方离婚起诉书
2015/05/18 职场文书
开业庆典致辞
2015/08/01 职场文书