如果 JavaScript 中的 var 定义了两次,解释器应该采用哪个定义?

If a var in JavaScript is defined twice, which definition should the interpreter take?

我是 JavaScript 的新手,正在尝试理解提升和作用域的概念。

案例一

var name;

function logName(num) {
  console.log(name, num);
}

logName(1);
name = "Auro";
logName(2);

并且我在控制台中有以下输出

Auro 1
Auro 2

如果我没理解错hoisting,JS引擎是先吊起一个变量的声明,然后自动给它赋值undefined。只有当它遇到赋值(=)运算符时,它才真正给它赋值。

如果我上面的理解是正确的,那么第一次调用logName函数时,变量name应该打印undefined,但它打印的是值。

案例二

var name;

function logName(num) {
  console.log(name, num);
}

logName(1);
name = "Auro";
logName(2);
name = "Baner";

控制台输出:

Baner 1
Auro 2

这让我更加困惑。这里函数 logName 的第一次调用选择了后来对变量的赋值并打印了 Baner,然而,第二次调用选择了之前的赋值,即 Auro.

这是怎么回事?我错过了什么?

除了我可以说的其他答案之外,只是不使用 var 而是使用 ES6 letconst 而 'surprising behaviour' 将会消失。

let name;

function logName(num) {
  console.log(name, num);
}

logName(1);
name = "Auro";
logName(2);
name = "Baner";

在全局范围内,name 指的是 window.name,即 window 的 name 属性 - 在您给出的示例中是 sif1sif2(可能是 "Snippet IFrame 1/2")。

因为 window.name 已经存在,所以 var name; 在全局范围内什么都不做。变量已定义。

直到你覆盖它 - 请注意你再次设置全局 window.name 属性。而且,根据浏览器设置,这可以在页面重新加载时持续存在(因为您正在命名整个 window)。这解释了为什么您会看到值 "stick".

指定输出中没有 none 匹配,因为最初 name 的值等于 window.name,所以最初 name 变量的值将相等到 winow.name 并在覆盖它后得到新值

让我们了解这一切是如何运作的

你可以这样理解代码执行有两个阶段

  1. 创作阶段
  2. 执行阶段

创建阶段:-创建阶段函数原样吊顶,变量吊顶但没有分配给它的值(或者你可以说它的值是未定义的)

执行阶段:- 在执行上下文期间,它会在到达发生赋值的行时为变量赋值

var name;

function logName(num) {
  console.log(name, num);
}

logName(1);
name = "Auro";
logName(2);
name = "Baner";