繁体   English   中英

函数定义为参数的关闭

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM