关闭函数定义为参数

时间:2018-03-04 15:32:09

标签: javascript closures

免责声明:这个问题纯粹是好奇心驱使,必须对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,但确实如此。

我怀疑当在参数空间中定义一个函数时会发生什么,它实际上是在被指定为参数之前定义但没有证明。任何指针都高度赞赏。

非常感谢。

2 个答案:

答案 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”的值。