理解循环中的闭包

时间:2013-03-01 00:45:58

标签: javascript functional-programming closures

function f() {
  function makeClosure(x) {
    return function(){
      return x;
    }
  }
  var a = [];
  var i;
  for(i = 0; i < 3; i++) {
    a[i] = makeClosure(i);
  }
  return a;
}

var gg = f()
gg[1]()

我非常接近理解闭合我可以品尝它:)...我得到了机制,我仍然只是在构思上有点麻烦。

我确信这是一个过时的过度简化,但在上述情况下,以下列方式思考发生的事情是否准确?

  1. 函数f()被称为
  2. 函数makeClosure被调用并被赋予参数index [1]
  3. 函数makeClosure调用匿名函数并为其赋予参数index [1]
  4. for statement starts
  5. for语句迭代然后调用函数makeClosure
  6. function makeclosure然后测试参数index [0]是否与匿名函数的参数
  7. 匹配
  8. makeClosure函数和匿名函数不匹配
  9. 循环第二次迭代,产生参数index [1]
  10. function makeclosure然后测试参数index [1]是否与匿名函数的参数
  11. 匹配
  12. 匹配
  13. 退出makeClosure函数,函数f()返回var a,此时保存为数字1
  14. 对不起,如果它长篇大论,我只是想让我的理解并非完全有缺陷。谢谢!

2 个答案:

答案 0 :(得分:1)

由于这是一个寻求对闭包的一般理解的问题,这里是一般规则。

If a function is declared within another function as opposed to invoked (this is an important distinction), the inner function has access to the scope of the function it is declared in.

现在谈谈这个问题的具体细节。 第6点之后的所有内容看起来都与目前发布的代码不同。因此,我将仅描述循环正在做什么。

循环从0到2,用函数填充数组。在这些函数的范围内,它们分别具有值0,1和2.因此,最后一行gg[1]()调用数组索引1处的函数,该函数返回值1.

另一种概念化的方法是在循环期间创建一个具有属性x的对象。该对象有一个无名方法,它返回x。

希望这能让您更好地了解闭包是什么。就个人而言,我喜欢将闭包视为范围规则而不一定是一种对象。

答案 1 :(得分:0)

  
      
  1. 函数f()被称为
  2.   

首先,建立全局代码环境,并处理fgg的声明。然后语句分配给gg,这会导致f被调用。

  

2。调用函数makeClosure并赋予参数index [1]

还没有。循环开始后调用该函数(#5)。

当调用f时,会创建一个新的执行上下文并建立其环境,makeClosureai被创建为局部变量,即全局对象放在其范围链上。然后为a分配一个新的empy数组。

  

3。函数makeClosure调用匿名函数并赋予它参数index [1]

makeClosure内没有来电。

  

4。声明开始   。   5。 for语句迭代然后调用函数makeClosure

这发生在2之前。

最初调用

makeClosure,其值为0

调用makeClosure时,会创建一个新的执行上下文。它有一个形式参数x,第一次分配值0,第二次分配1,依此类推。

makeClosure的范围链上有f的执行对象,因此它可以访问所有f的参数和变量。 Samed命名的标识符被本地标识符“shaddowed”。

每次调用时,makeClosure都会返回一个没有变量或形式参数的函数对象。这些函数对象有一个范围链,它在创建它们时定义并包含它们自己,然后是makeClosure的执行上下文的实例,然后是f,然后是全局执行上下文。 / p>

返回的函数对象被分配给a的成员。

  

6。函数makeclosure然后测试参数index [0]是否与匿名函数的参数匹配   7。 makeClosure函数和匿名函数不匹配   8。循环迭代第二次产生参数索引[1]   9。函数makeclosure然后测试参数index [1]是否与匿名函数的参数匹配   10。他们匹配   11。退出makeClosure函数,函数f()返回var a,此时保存为数字1

这一切都没发生。对于每个循环,对makeClosure进行了新的调用,因此返回一个新函数,在其作用域链上使用不同的makeClosure执行对象实例。这些已分配给a的成员。

for循环迭代3次,其中i的值为01则为2。当i到达3时,它会在执行前退出。

12。返回对数组(a)的引用并将其分配给全局g

13。调用g[1]。这引用了第二个返回的函数,然后调用它。当在其作用域链中解析该函数​​内的标识符x时,会找到创建它的x实例中的makeClosure。这对应于使用值1创建的值,因此x的值为1,将返回。

我可能搞砸了一些东西,但这或多或少都在发生。