在块范围内,即使在使用未定义的 var 类型的变量初始化后,也会记录出意外的值

In the block scope even after initialisation with undefined var type of variable logs out unexpected value

function show() {
  var x = 10;
  if (true) {
    var x = 20;
  }
  console.log(x); // 20
}

show();

但是当我没有手动初始化 'if-statement' 中的 'x' 时,它用 undefined 初始化并提升到顶部并且应该记录最近的值是 undefined ,因为 20 在上面的例子中是注销的。但是它注销 10.Why?

function show() {
  var x = 10;
  if (true) {
    var x;
  }
  console.log(x); // 10
}

show();

来自 MDN - var:

Duplicate variable declarations using var will not trigger an error, even in strict mode, and the variable will not lose its value, unless another assignment is performed.

因此,除非您将任何值重新分配给 x,否则使用 var 声明的变量将保留其值。

if 块中重新声明 x 不会创建新变量; x 仅创建一次。

来自Ecmascript spec - 14.3.2 Variable Statement:

A var statement declares variables that are scoped to the running execution context's VariableEnvironment. Var variables are created when their containing Environment Record is instantiated and are initialized to undefined when created. Within the scope of any VariableEnvironment a common BindingIdentifier may appear in more than one VariableDeclaration but those declarations collectively define only one variable.

这就是为什么x在下面的语句

var x;

不会隐式地使用 undefined 进行初始化;此重新声明语句没有重新创建变量 x.

function show() {
  var x = 10;
  if (true) {
    var x = undefined; // re-assigned
  }
  console.log(x);
}

show();


关于提升的注意事项: 除非您已经知道这一点,否则变量不会按字面意思 hoisted/moved 到声明它们的范围的顶部;变量声明在代码执行之前处理,这就是为什么它们看起来已移至范围顶部的原因。

详情请见:MDN - var hoisting

因此,如果您试图将以上两个示例联系起来,您可能会感到困惑。换个角度看这两个例子,你就会得到答案。