Javascript 无法理解一个技巧变量“提升”:为什么它是 NaN 值

Javascript Couldn't understand a trick variable "hoisting": why it's NaN value?

本文关键字:提升 变量 为什么 NaN 一个 Javascript      更新时间:2023-09-26

我尝试了JavaScript来理解它的提升策略,但更加困惑:

function f(i){this.i+=i}
i=2
f(3)
console.log(i)

它输出

5

(1(这是我所期望的。然后我尝试重新定位"i=2"语句:

function f(i){this.i+=i}
f(3)
console.log(i)
i=2

它输出

NaN

(2(这是为什么呢?我预料到,因为"i"被吊到整个程序的前面,为什么它打印"NaN"?一个可能的答案是,编译器将程序重构为:

var i
function f(i){this.i+=i}
f(3)
console.log(i)
i=2

(3(所以当"console.log(i("时,我没有被分配任何值,所以它是"NaN"--->但我尝试了下面的程序:

function f(i){this.i+=i}
f(3)
i=2
console.log(i)

如果上面的解释是正确的,我希望这也应该输出"NaN"。但实际上,它输出

2

这就更诡异了。在这种情况下,"吊装"是否有效?

(4(更有趣的是,如果我将程序更改为:

var i
function f(i){this.i+=i}
f(3)
console.log(i)
i=2

然后它输出

undefined

为什么?

(5(对于程序:

var i
function f(i){this.i+=i}
f(3)
i=2
console.log(i)

它再次输出

2

您能否解释一下上述观察结果,因为它确实来自我对"吊装"的理解?

正如@zzzzBov所指出的,这与提升无关,而与上下文范围有关,特别是在非严格模式环境中。

function f(i){this.i+=i}
i=2
f(3)
console.log(i)

i=2相当于window.i=2。由于这是在非严格模式下,thiswindow,所以this.i+=i等价于window.i+=i,其中右手i由函数参数提供。所以这应该解释5的输出。

function f(i){this.i+=i}
f(3)
console.log(i)
i=2

这里唯一的区别是i=2是在this.i+=i之后执行的。向未声明的变量添加数字会导致NaN按预期。

var i
function f(i){this.i+=i}
f(3)
console.log(i)
i=2

在这里,var i附加到window作用域,因为它处于非严格模式,因此this.i+=i向声明但未初始化的值 window.i 添加一个数字,这仍然会导致NaN

var i
function f(i){this.i+=i}
f(3)
i=2
console.log(i)

在这里,希望是很明显的。 i=2将覆盖之前发生的一切(在这种情况下是isNaN(i)===true.

有问题吗?下课了。

要记住的一件非常重要的事情是,Javascript 只会提升函数声明,而不是在调用函数时。

function f(i) { ... } //will be hoisted
f(2); //won't be hoisted

继续前进...

我试图重新定位"i=2"语句...它输出NaN ...为什么?我预料到,因为"i"被吊到整个程序的前面,为什么它打印"NaN"?

function f(i){this.i+=i}
f(3) //the function executes i = undefined+3, which is NaN
console.log(i) //i is logged, which is currently NaN
i=2 //i has the value of 2 assigned to it

这输出NaN因为当一个被undefined的变量被视为Number时,它就会变得NaN

我希望这也应该输出"NaN"。但实际上,它输出2 这就更诡异了。在这种情况下,"吊装"是否有效?

function f(i){this.i+=i}
f(3) //the function executes i = undefined+3, which is NaN
i=2 //i has the value of 2 assigned to it
console.log(i) //i is logged, which is currently 2

这会输出2因为i在记录i之前被分配了 2 的值。

。它输出undefined这是为什么?

var i //i is undefined
function f(i){this.i+=i} //f is hoisted and is line 1
f(3) //the function assigns (undefined + 3) to a variable which is never referenced
console.log(i) //i is logged, which is currently undefined
i=2 //i has the value of 2 assigned to it

undefined输出i因为在记录之前从未为其分配过值。

它再次输出2

var i //i is undefined
function f(i){this.i+=i} //f is hoisted and is line 1
f(3) //the function assigns (undefined + 3) to a variable which is never referenced
i=2 //i has the value of 2 assigned to it
console.log(i) //i is logged, which is currently 2

这会输出2因为i在记录i之前被分配了 2 的值。

仅仅因为定义了 i,并不意味着它具有数据类型。在 JavaScript 中,只有几种集合数据类型,Number 就是其中之一。

如果没有事先赋值,函数就无法知道您使用的是"重载"加操作数中的数字还是字符串。

通过提升,它不排除指令的流动,只是在发生变量声明的地方。如果变量未初始化,则在第一次赋值之前,它将保持为非类型化变量。