为什么 JavaScript 的空合并运算符 (||) 不适用于 es6 变量 (let/const)?

Why does JavaScript's null coalescing operator (||) not work with es6 variables (let/const)?

为什么 var APP = APP || {}; 工作正常,但 const APP = APP || {}; 不行?或者 let APP = APP || {} 就此而言。

Uncaught ReferenceError: APP is not defined

因为这只与APP的评估有关,与它的设置无关。

Why does var APP = APP || {}; work fine, but const APP = APP || {}; not?

让我们阐明如何评估这些语句。在执行任何代码之前,运行时会查找所有变量声明并在当前范围内为每个声明创建一个条目。一段时间后,当 APP = APP || {} 被执行时,APP 的值在被赋值之前被读取。

它 "works" 和 var,因为 var 声明是 隐式 使用值 undefined 初始化的。因此在赋值之前访问变量 returns undefined.

然而,

constlet 声明 未初始化 。在为它们分配初始声明的值之前,您无法访问它们。这也简称为 TDZ

这是一个简化的例子:

console.log(foo); // undefined
var foo = 42;
console.log(foo); // 42

console.log(foo); // ReferenceError because of TDZ
let foo = 42;
console.log(foo); // 42 in theory, but this line is never executed due to the error above

来自 MDN:

In ECMAScript 2015, let bindings are not subject to Variable Hoisting, which means that let declarations do not move to the top of the current execution context. Referencing the variable in the block before the initialization results in a ReferenceError (contrary to a variable declared with var, which will just have the undefined value). The variable is in a "temporal dead zone" from the start of the block until the initialization is processed.

同样适用于const:

All the considerations about the "temporal dead zone" apply to both let and const.

换句话说,这是有效的原因:

var APP = APP || {};

是因为变量提升将上面的内容翻译成:

var APP;          // <-- declares APP
APP = APP || {};  // <-- initializes APP

并且由于变量提升不适用于 letconst:

const APP = APP || {}; // <-- Fails because APP is not yet initialized.
let APP = APP || {};   // <-- Fails for the same reason.

最后,郑重声明(正如 naomik 正确指出的那样),|| 运算符 不是 空合并运算符,而是一个短路或运算符.

对此的混淆可能是因为这样的陈述:

var n = n || '';

对于上面的说法,有两点需要牢记。

  1. n 不是 null... 它是 undefined(不同于 null).

  2. 由于变量提升,该语句等同于:

    var n;        // n has the value of undefined
    n = n || '';  // the comparison is now: undefined || '';
    

并且由于 undefined 是一个 "falsy" 值,所以短路 OR 运算符 returns 第二个值。

此行为也适用于 null因为 null 也是 "falsy"。