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 相关文章推荐
JS target与currentTarget区别说明
Aug 28 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(五)可移动地图的实现
Jan 23 Javascript
jquery()函数的三种语法介绍
Oct 09 Javascript
编写高效jQuery代码的4个原则和5个技巧
Apr 24 Javascript
jQuery学习笔记之 Ajax操作篇(三) - 过程处理
Jun 23 Javascript
jquery实现多条件筛选特效代码分享
Aug 28 Javascript
禁用backspace网页回退功能的实现代码
Nov 15 Javascript
原生js编写焦点图效果
Dec 08 Javascript
JavaScript基于Dom操作实现查找、修改HTML元素的内容及属性的方法
Jan 20 Javascript
AngularJS全局警告框实现方法示例
May 18 Javascript
最实用的JS数组函数整理
Dec 05 Javascript
js实现提交前对列表数据的增删改查
Jan 16 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
在IIS7.0下面配置PHP 5.3.2运行环境的方法
2010/04/13 PHP
php使用ICQ网关发送手机短信
2013/10/30 PHP
PHP 自动加载的简单实现(推荐)
2016/08/12 PHP
php判断文件上传图片格式的实例详解
2017/09/30 PHP
kindeditor 加入七牛云上传的实例讲解
2017/11/12 PHP
YII框架关联查询操作示例
2019/04/29 PHP
jQuery UI Dialog控件中的表单无法正常提交的解决方法
2010/12/19 Javascript
解析URI与URL之间的区别与联系
2013/11/22 Javascript
你未必知道的JavaScript和CSS交互的5种方法
2014/04/02 Javascript
jQuery中change事件用法实例
2014/12/26 Javascript
JS扩展方法实例分析
2015/04/15 Javascript
js父页面中使用子页面的方法
2016/01/09 Javascript
EasyUI学习之Combobox下拉列表(1)
2016/12/29 Javascript
原生js实现简单的链式操作
2017/07/04 Javascript
AngularJS实现的生成随机数与猜数字大小功能示例
2017/12/25 Javascript
详解vue挂载到dom上会发生什么
2019/01/20 Javascript
小程序中this.setData的使用和注意事项
2019/08/28 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
vue element-ul实现展开和收起功能的实例代码
2020/11/25 Vue.js
JS实现鼠标移动拖尾
2020/12/27 Javascript
[02:56]DOTA2亚洲邀请赛 VG出场战队巡礼
2015/02/07 DOTA
[04:03][TI9趣味短片] 小鸽子茶话会
2019/08/20 DOTA
利用Python脚本在Nginx和uwsgi上部署MoinMoin的教程
2015/05/05 Python
Python按行读取文件的实现方法【小文件和大文件读取】
2016/09/19 Python
Python实现XML文件解析的示例代码
2018/02/05 Python
Python实现简单生成验证码功能【基于random模块】
2018/02/10 Python
python保存网页图片到本地的方法
2018/07/24 Python
基于Python的OCR实现示例
2020/04/03 Python
jupyter notebook更换皮肤主题的实现
2021/01/07 Python
意大利宠物用品购物网站:Bauzaar
2018/09/15 全球购物
金讯Java笔试题目
2013/06/18 面试题
介绍一下SQL Server里面的索引视图
2016/07/31 面试题
DIY蛋糕店的创业计划书范文
2013/12/26 职场文书
2014年秋季开学演讲稿
2014/05/24 职场文书
2017春节晚会开幕词
2016/03/03 职场文书
实用求职信模板范文
2019/05/13 职场文书