幕后的函数表达式真正发生了什么?

spa*_*117 4 javascript ecmascript-6

我正在遍历freecodecamp上的javascript基础,只是为了刷新自己的记忆,当我进入ES6并解释varlet之间的差异时,其中一个示例使我(和我的同事)头疼。

'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
    if (i === 2) {
        printNumTwo = function() {
            return i;
        };
    }
}

console.log(printNumTwo());
// returns 2

console.log(i);
// returns "i is not defined"
Run Code Online (Sandbox Code Playgroud)

我期望该printNumTwo函数返回undefined,以为到该函数被调用时该变量i不存在。我的一位同事说,将函数表达式分配给变量时,i得到的值为,2因此当您调用函数时,它将始终返回2

为了验证该理论,我们将原始示例修改为:

'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
    if (i === 2) {
        printNumTwo = function() {
            return i;
        };
        
        i++;
    }
}

console.log(printNumTwo());
// returns 3

console.log(i);
// returns "i is not defined"
Run Code Online (Sandbox Code Playgroud)

令每个人都惊讶的是,在for循环之后调用该函数3而不是返回2或返回最初的预期undefined

谁能解释一下这种行为的原因吗?将函数表达式分配给变量或调用该表达式时,会发生什么?

Nic*_*wer 5

您正在制作和使用闭包。闭包是一个函数,加上声明它的环境。当您编写以下代码行时:

printNumTwo = function() {
  return i;
};
Run Code Online (Sandbox Code Playgroud)

该函数引用了i变量。只要此函数存在,该变量就不会被垃圾回收,并且可以继续被该函数引用。它不是保存值的快照,而是保存对实际变量的引用。如果该变量发生变化(如第二个示例中所示),则引用将看到该修改后的值。