我知道函数声明被提升到其作用域的顶部。这允许我们在 JavaScript 中实际声明之前使用这些函数:
sayHello(); // It works!
function sayHello() {
console.log('Hello');
}
我还了解到闭包使函数能够保留对在同一范围内声明的变量的引用:
function outerFxn() {
let num = 0;
function innerFxn() {
console.log(num);
num++;
}
return innerFxn;
}
const logNum = outerFxn();
logNum(); // 0
logNum(); // 1
logNum(); // 2
到目前为止一切顺利。但这里有一些奇怪的地方,我希望有人能准确解释发生了什么......
场景一:可理解的闭包
function zero(cb) {
return setTimeout(cb, 0);
}
function test1() {
let txt = 'this is a test message';
function log() {
console.log(txt);
}
zero(log);
}
在上面的示例中,log
函数保留对其创建范围的引用,保存在 txt
变量中。然后,当稍后在 setTimeout
中执行时,它成功记录了 txt
变量的值。伟大的。然后就是这个...
场景 2:发生了什么?
function zero(cb) {
return setTimeout(cb, 0);
}
function test1() {
function log() {
console.log(txt);
}
let txt = 'this is a test message';
zero(log);
}
我已将 log
函数声明移动到范围的顶部(无论如何它都会被提升到那里,对吧?),然后我正在声明txt
变量在它下面。这一切仍然有效,我不确定为什么。当 let
和 const
未提升时,log
如何保留对 txt
变量的引用向上?是否对闭包作用域作为一个整体进行了分析?我可以在这里逐步说明 JavaScript 引擎正在做什么。谢谢你!
最佳答案
它是您离开 test1
函数后作用域的一部分。此时它是否与 var
、let
或 const
一起使用并不重要。由于对整个 body 进行了评估,因此该变量存在于范围内。
如果您在评估 let
声明之前尝试使用 log
,则会收到错误。
编辑:从技术上讲,用 let
和 const
声明的变量在范围内,但它们被单元化,如果您尝试访问它们。只有在您到达声明时它们才会被初始化并且您可以访问它们。所以它们总是在范围内,只是在评估声明之前不可用。
关于JavaScript:理解闭包和提升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45461858/