这些闭包的例子有什么不同?

时间:2011-06-25 15:04:59

标签: javascript closures

我在每个测试用例中都有两种情况。我想了解其中的差异,并希望更多地了解闭包。

测试1:

somefunction(someobj);

somefunction(function(){ return someobj; });

测试2

for(;;){
  someoperations;
}

for(;;)(function(iterator){
  someoperations;
})(iterator);

测试3:

var x = (function() {
  return {};
})();

(function() {
  //this = window
  var x = function() {
    //this = instance of x
    this.something = somethingelse;
  }
  //making it global OR making it available outside closure.
  return (this.x=x);
})();

我需要解释在每个测试用例中以第二种方式使用它的优点是什么。

2 个答案:

答案 0 :(得分:3)

在javascript中,创建新变量范围的唯一方法是在函数中。

是否需要新范围将完全取决于具体情况。因此,您提供的一般示例不允许明确的答案。


为了提供更具体的内容,请接受我们的测试2 ,并应用这种非常常见的情况,其中someoperations异步调用,如{ {1}}:

setTimeout

问题是在循环中创建的每个函数(并传递给for( var i=1; i<4; i++ ) setTimeout( function() { alert( i ); }, 1000 * i); )引用相同的setTimeout变量,因为它是i,它是非阻塞的,循环在完成循环中创建的任何函数之前完成。

结果是每个函数都会提醒setTimeout,因为那是循环后4的值。

示例: http://jsfiddle.net/Ng3rr/


另一方面,如果调用循环中设置i的函数,将setTimeout的值传递给该函数,则引用的变量发送到i的每个函数都将是本地setTimeout,它引用了传递给该外部调用的值。

(我称之为inner_i来区分两者,但你也可以命名内部变量inner_i。这样做称为变量阴影。)

i

现在每个警报都会显示每次迭代时收到的值。

正如您所看到的,这完全取决于具体情况。

示例: http://jsfiddle.net/Ng3rr/1/


为了在上面的示例中添加一些对比,如果我们没有在循环中运行任何异步代码,那么外部函数将是不必要的。

此:

for( var i=1; i<4; i++ )(function( inner_i ){
  setTimeout( function() { alert( inner_i ); }, 500 * inner_i);
})( i );

示例: http://jsfiddle.net/Ng3rr/2/

......而且这个:

for( var i=1; i<4; i++ ) alert( i );

示例: http://jsfiddle.net/Ng3rr/3/

...将具有相同的行为,使外部功能变得不必要。


因此,调用外部函数会创建一个新的变量范围。在该新范围中,变量将由在该范围内创建的任何其他嵌套函数保留。

此外,虽然在该范围内创建的变量可以在嵌套在该范围内的函数中访问,但它们在范围之外不可用。这样可以防止使用其他变量名来污染周围的范围。

答案 1 :(得分:0)

让我们回答,不限于JavaScript。

有几种方法可以将函数用作变量/参数,其中一种嵌套在另一个函数中,称为&#34; closure&#34;。

您可以查看&#34;关闭&#34;的完整描述。这里:

http://en.wikipedia.org/wiki/Closure_%28computer_science%29

我建议对很长的扩展代码使用单独的函数(case 1),对短代码使用嵌套函数(case 2)。