逻辑赋值运算符的作用是对逻辑运算符和赋值表达式的简写。
如果要判断一个变量是否为 false,如果为 false 则给它重新赋值,通常的写法为:
function example(a) {
if(!a) {
a = 'foo';
}
}
同样也可以简写为:
function example(a) {
a = a || 'foo';
}
example();
有了逻辑赋值运算符后,我们可以这样写:
function example(a) {
a ||= 'foo';
}
example();
逻辑赋值运算符可以搭配更多的逻辑运算符使用:
a ||= "foo"; // a 为 false 时,foo 将会被赋值给 a。 (a = true 时会触发逻辑短路,后面不执行)
a &&= 'foo'; // a 为 true 时,foo 将会被赋值给 a。(a = false 时会触发逻辑短路,后面不会执行)
a ??= 'foo'; // a 为 null 或者 undefined 时,foo 将会被赋值给 a
逻辑赋值运算符和数学运算符的区别
数学运算符会触发对象上的 set 操作,逻辑赋值运算符在「逻辑短路」时不会触发 set 操作。
let x = 0;
const obj = {
get x() {
return x;
},
set x(val) {
console.log('setter called');
x = val;
}
}
obj.x += 1; // 数学运算符进行赋值,会触发 set 方法
obj.x ||= 2; // 因为 obj.x 的值为 1,触发「逻辑或」的逻辑短路,于是不会触发 set 方法
obj.x &&= 3; // 因为 obj.x 的值为 2,且是「逻辑与操作」,会出发 set 方法
绝大多数情况下,逻辑短路是否触发 set 方法对于性能的影响并不大,但是有时候触发 set 方法会带来一些副作用(side effect),例如:
document.getElementById('preivewZone').innerHTML ||= '<i>Nothing to preview.</i>';
上面代码中,如果 .innerHTML
的 set 方法没有被调用,那么该 HTML 元素的一些状态不会消失(例如元素的 focus 状态)。
此提案于 2021 年提出,目前已经通过了 ECMA 的 stage 4,推荐使用。
参考:
https://github.com/tc39/proposal-logical-assignment
https://developer.cdn.mozilla.net/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND_assignment
NEXTH5 中阻止浏览器前进后退手势