逻辑赋值运算符

 

逻辑赋值运算符的作用是对逻辑运算符和赋值表达式的简写。

如果要判断一个变量是否为 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