免责声明:这个问题纯粹是好奇心驱使,必须对javascript的运作方式做很多。
我理解为什么以下代码有效。由于关闭,foo可以访问所在的范围。这是有道理的。
var a = 10
var foo = function(){
console.log(a);
}
setTimeout(foo,1000)
但是,我想知道为什么以下内容也有效(后面会解释)。
var a = 10
setTimeout(function(){
console.log(a);
},1000)
该函数在接收它的函数的参数中定义,并且基本上从不是包含a
的范围的闭包。我们知道当一个函数接收一个参数时,它会为该参数创建一个局部变量,例如
var outerVar="5"
var bar = function(a){
//implicitly, var a = outerVar happens here
console.log(a)
}
bar(something);
因此遵循该逻辑,传递给setTimeout
的函数无法访问a
,但确实如此。
我怀疑当在参数空间中定义一个函数时会发生什么,它实际上是在被指定为参数之前定义但没有证明。任何指针都高度赞赏。
非常感谢。
答案 0 :(得分:2)
它并非完全关闭,但它已经关闭了。
严格来说,闭包是指一个变量的范围结束,但仍然包含在仍然存在的内部函数中:
df1 <- data.frame(col1 = 1:5,
col2=c("Sydney, Australia", "Aarhus C, Central Region, Denmark", "Auckland, New Zealand", "Mumbai Area, India", "Singapore"),
stringsAsFactors = FALSE)
df2 <- data.frame(col1=1:7,
col2=c("India", "USA", "New Zealand", "UK", "Singapore", "Denmark", "China"),
stringsAsFactors = FALSE)
已定义function createTimer() {
let counter = 0;
return function() {
return counter++;
}
}
const timer = createTimer(); // function() { ... }
console.log(timer(), timer(), timer()); // 0, 1, 2
的函数已返回,范围已结束,并且在正常情况下,counter
应该已经死亡并且已收集垃圾。但是从counter
返回的内部函数仍然有一个对它的引用,来自封闭范围,这是一个闭包。
在JavaScript中,每个函数都可以访问其所有祖先的所有范围,这就是你在这里看到的。
传递给createTimer()
的函数可以访问setTimeout()
,因为a
是在其周围的范围内定义的。
答案 1 :(得分:0)
当你查看javascript代码并查看它是如何工作的时候,根据我的最佳方法是首先了解javascript引擎的工作原理。
首先,它遍历代码并将所有变量分配给范围,并在第二个跟踪中进一步根据范围分配值。
所以在你的第一个代码中, 引擎首先遍历并分配 var a到全局范围, var foo作为全球范围, 然后当setTimeout运行时,它调用foo函数并将a的值记录为全局a的值,因为它没有任何本地“a”,因此检查词法范围。
在你的第二个代码中,
Var a又是全局作用域 这次没有其他声明。 在第二个遍历中,它将值10分配给a并解释settimeout并打印值
在你的第三个代码中, 与第二个相同,除了“foo”赋予settimeout函数的事实,你编写了你的回调函数,然后自己编写。
当它执行setTimeout时, 您的每个代码都在其访问的全局范围内具有“a”的值。