[英]Closure of function defined as an argument
免责声明:这个问题纯粹是出于好奇心,与JavaScript的工作方式有很大关系。
我了解以下代码为何有效。 由于闭包,foo可以访问a所驻留的范围。 这是有道理的。
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
,但是可以。
我怀疑当在参数空间中定义一个函数时,会发生的事情是,它确实在被分配为参数之前就已定义,但没有证明。 任何指针高度赞赏。
谢谢你
它不是完全关闭,但是很接近。
严格来说,闭包是指变量的作用域结束时,但仍封闭在仍存在于内部函数中的内部函数中:
function createTimer() {
let counter = 0;
return function() {
return counter++;
}
}
const timer = createTimer(); // function() { ... }
console.log(timer(), timer(), timer()); // 0, 1, 2
定义counter
的函数已返回,作用域已终止,并且在正常情况下, counter
应已死亡并收集垃圾。 但是从createTimer()
返回的内部函数仍然具有对它的引用(从封闭的范围开始) ,即封闭。
在JavaScript中,每个函数都可以访问其所有祖先的所有范围,这就是您在此处看到的。
传递给setTimeout()
的函数可以访问a
因为在其范围内定义a
a
。
当您查看javascript代码并查看其工作方式时,根据我的最佳方法是首先了解javascript引擎的工作方式。
首先,它遍历代码并将所有变量分配给范围,并且在第二次跟踪中,它根据范围分配值。
因此,在您的第一个代码中,引擎首先遍历并将var a分配给全局作用域,将var foo分配给全局作用域,然后在setTimeout运行时调用foo函数,并将a的值记录为全局a的值,因为它没有任何局部值因此,“ a”检查词法作用域。
在第二个代码中
Var a还是全局范围的,这次没有其他声明。 在第二遍历中,它将值10分配给a并解释settimeout并打印该值
在您的第三个代码中,与第二个代码相同,不同的是,相反,“ foo”给了settimeout函数,您编写了回调函数,然后在其中写了n。
在执行setTimeout的时间l之前,您的每个代码在它们正在访问的全局范围中都有“ a”的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.