两个新出的 JavaScript 运算符
在 ECMAScript 2021(ES12)中,JavaScript 引入了新的逻辑赋值操作符 &&= 和 ??=。这些操作符将逻辑运算符与赋值运算符相结合,提供了更加简洁、直观的赋值方式。
虽然已经进入标准比较久了,但是我在实际开发中见到的还比较少,今天我们一起来学习下。
逻辑与赋值操作符 &&=
&&= 的工作原理
&&= 操作符是逻辑与运算符(&&)和赋值运算符(=)的结合。它的作用是:仅当左侧变量为真值(truthy)时,才将右侧的值赋给左侧变量。传统的写法需要使用 if 语句或逻辑运算符,&&= 则提供了更为简洁的方式。
传统写法对比:
// 使用 if 语句
if (x) {
x = y;
}
// 使用逻辑与运算符
x = x && y;
// 使用 `&&=` 操作符(ES2021)
x &&= y;
真值和假值的概念
在 JavaScript 中,以下值被认为是假值(falsy):
false0''(空字符串)nullundefinedNaN
其他所有值都被视为真值(truthy)。
示例解析
示例 1:用户登录状态
let isLoggedIn = true;
isLoggedIn &&= getUserData(); // 如果已经登录,获取用户数据
function getUserData() {
return { name: 'ConardLi', age: 17 };
}
// 结果:isLoggedIn 变为 { name: 'ConardLi', age: 17 }
示例 2:库存更新
let stock = 17;
function sell(quantity) {
stock >= quantity &&= stock - quantity;
}
sell(5); // stock 为 5
sell(17); // stock 保持为 5,因为 5 >= 17 为 false
在上述示例中,sell 函数仅在库存足够时才减少库存,防止出现负库存的情况。
应用场景
(1)条件更新属性
let config = {
debugMode: true,
logLevel: null
};
// 仅当 debugMode 为真时,设置 logLevel
config.debugMode &&= (config.logLevel = 'verbose');
// 结果:config.logLevel 为 'verbose'
(2)链式判断
let user = {
isActive: true,
hasMembership: true
};
// 仅当用户活跃且有会员资格时,给予折扣
user.isActive &&= user.hasMembership &&= applyDiscount();
function applyDiscount() {
return '已应用折扣';
}
// 结果:user.hasMembership 变为 '已应用折扣'
空值合并赋值操作符 ??=
??= 的工作原理
??= 操作符结合了空值合并运算符(??)和赋值运算符(=)。它的作用是:仅当左侧变量为 null 或 undefined 时,才将右侧的值赋给左侧变量。这有助于在变量未被初始化时提供默认值。
传统写法对比:
// 使用 if 语句
if (options.timeout === null || options.timeout === undefined) {
options.timeout = 3000;
}
// 使用空值合并运算符
options.timeout = options.timeout ?? 3000;
// 使用 `??=` 操作符(ES2021)
options.timeout ??= 3000;
与其他赋值方式的比较
问题:
- 逻辑或
||: 会将0、''、false等合法值视为需要赋默认值的情况,可能导致意外的结果。
let delay = 0;
delay = delay || 1000; // delay 被误赋值为 1000
解决方案:
??=: 仅在变量为null或undefined时才赋值,避免了上述问题。
let delay = 0;
delay ??= 1000; // delay 保持为 0
使用三元运算符:
user.name = (user.name !== null && user.name !== undefined) ? user.name : 'Anonymous';
问题: 代码较为冗长,可读性不高。
使用 ??=:
user.name ??= 'Anonymous';
优势: 简洁明了,仅在变量为 null 或 undefined 时才赋值,不影响其他假值。
应用场景
??= 操作符非常适合为可能未定义的变量设置默认值,且不会干扰有效的假值。
示例:
let score = 0;
score ??= 100; // 保持为 0
let tag = '';
tag ??= 'default'; // 保持为 ''
let active = false;
active ??= true; // 保持为 false
配置默认参数:
function initializeSettings(settings) {
settings.theme ??= 'light';
settings.notificationsEnabled ??= true;
settings.autoSaveInterval ??= 300;
return settings;
}
最后
JavaScript 的 &&= 和 ??= 操作符为我们提供了更为简洁和精确的赋值方式:
&&=操作符: 仅在左侧变量为真值时才进行赋值,适合用于需要在保持假值的同时,根据真值条件更新变量的场景。??=操作符: 仅在左侧变量为null或undefined时才进行赋值,适合用于为未定义或空值变量设置默认值的场景。
两个新出的 JavaScript 运算符的更多相关文章
- javascript运算符语法概述
× 目录 [1]个数 [2]优先级 [3]结合性[4]类型[5]规则表 前面的话 javascript中的运算符大多由标点符号表示,少数由关键字表示,它们的语法言简意赅,它们的数量却着实不少.运算符始 ...
- JavaScript 运算符
JavaScript 运算符 JavaScript 运算符用于赋值,比较值,执行算术运算等. JavaScript 算术运算符 算术运算符用于执行两个变量或值的运算. 赋值 y = 5, 以下表格将向 ...
- JavaScript运算符有哪些
JavaScript中的运算符有很多,主要分为算术运算符,等同全同运算符,比较运算符,字符串运算符,逻辑运算符,赋值运算符等.这些运算符都有一些属于自己的运算规则,下面就为大家介绍一下JavaScri ...
- JavaScript运算符:递增递减运算符前置和后置的区别
从两段代码说起 var num1 = 2; var num2 = 20; var num3 = --num1 + num2; var num4 = num1 + num2; console.log(n ...
- java基础59 JavaScript运算符与控制流程语句(网页知识)
1.JavaScript运算符 1.1.加减乘除法 加法:+(加法,连接符,正数) true是1,false是0 减法:- 乘法:* 除法:/ 1.2.比较运算符 ...
- JavaScript运算符:递增和递减(++i,--i 和 i++,i-- 的区别)
递增和递减操作符直接借鉴自C,而且各有两个版本:前置型 (递增 ++i ,递减 --i )和 后置型 (递增 i++ ,递减 i-- ).书本上对两者的定义是:前置型应该位于要操作的变量之前,而后置型 ...
- javaScript运算符学习笔记
1.赋值运算符 javaScript运算符可以分为简单赋值和复合赋值运算.简单赋值运算是将赋值运算符(=)右边的表达式的值保存到赋值运算符左边的变量中,复合赋值运算则是混合了其他操作(算术运算操作,位 ...
- JavaScript 运算符是什么?
㈠JavaScript 运算符 ⑴运算符 = 用于赋值. ⑵运算符 + 用于加值. ⑶示例: 向变量赋值,并把它们相加: ; // 向 x 赋值 5 ; // 向 y 赋值 2 var z = ...
- JavaScript运算符与流程控制
JavaScript运算符与流程控制 运算符 赋值运算符 使用=进行变量或常量的赋值. <script> let username = "YunYa"; < ...
- JavaScript运算符
JavaScript运算符 1.算数运算符 设定a = 5. 运算符 描述 例子 结果 + 加 b=a+2 b=7 - 减 b=a-2 b=3 * 乘 b=a*2 b=10 / 除 b=a/2 b=2 ...
随机推荐
- 网络问题mark
复杂且混乱的网络环境, 主内网是192.168.0.254(网关), 中间混杂无数网段 , 无数dhcp, 同时还有0段的外网(跟254没关系) 现在是有一台服务器 , 192.168.0.47 , ...
- CANopen学习笔记(二)通讯对象PDO和SDO等
通讯对象 PDO 我的观点:一个 CANopen 设备可以拥有最多 512 个 RPDO 和 512 个 TPDO,总共最多 1024 个 PDO.(得到GPT4o的肯定) CiA协议栈观点:一个只有 ...
- 【Python】之Mac使用图片识别pytesseract方法报错
一.前提: python中使用pytesseract图片识别,报错误: pytesseract.pytesseract.TesseractNotFoundError: tesseract is not ...
- 技术解析 | ZEGO 移动端超分辨率技术
即构超分追求:速度更快.效果更好.码率更低.机型更广. 超分辨率(Super Resolution, SR)是从给定的低分辨率(Low Resolution, LR)图像中恢复高分辨率(High ...
- ASP.NET Core – Razor Syntax
前言 Full stack 的问题就是经常需要一阵子离开一个环境. 比如我跑去写 Angular 几个月. 回来写 Razor, 肯定是卡卡的. 尤其是一些比较不常用到的语法. 所以有一个很好的笔记就 ...
- CSS – ellipsis and line-clamp
前言 CSS 很早就有 build-in 方案 for 省略号 ellipsis 了. 但是只能 one line, 遇到多行的时候只能用 JS. 后来出了 line-clamp 终于把 multip ...
- Hugging Face NLP课程学习记录 - 2. 使用 Hugging Face Transformers
Hugging Face NLP课程学习记录 - 2. 使用 Hugging Face Transformers 说明: 首次发表日期:2024-09-19 官网: https://huggingfa ...
- 26岁女生转行车载测试1年,月入15K~
年前有朋友找工作,跟我说简历改了车载后,收到的打招呼翻了几倍,如今车载测试前景非常广阔,因为越来越多的汽车厂商正在开发新的可智能化的汽车,他们需要测试这些汽车的性能,安全性以及可靠性.车载测试技术可以 ...
- 5G网元功能与接口
5G网元功能与接口 5G移动通信整体网络架构 5G网络功能之间的信息交互可以基于两种方式表示:其一为基于服务表示:其二为基于点对点表示.实时部署时,也可以采用两种方式相结合的表示方式. 并不是所有的接 ...
- [OI] 交互 | pipe
关于如何在本地实现交互 管道 Linux 内置了一种管道操作,可以方便地把 \(A\) 程序的输出和 \(B\) 程序的输入连接起来,只需要以下指令: A | B 此代码行的意思是:同时运行 \(A\ ...