【发布时间】:2017-08-02 13:12:17
【问题描述】:
我了解函数声明被提升到其范围的顶部。这允许我们在 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
到目前为止一切顺利。但是这里有一些奇怪的地方,我希望有人能准确地解释发生了什么......
场景 1:可理解的关闭
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 引擎正在做什么。谢谢你!
【问题讨论】:
-
你可以简单地使用这个替代 sn-p: function f() { console.log("a1: " + a); a = 123; console.log("a2: " + a) } 两个日志都打印 123
标签: javascript closures hoisting