我在每个测试用例中都有两种情况。我想了解其中的差异,并希望更多地了解闭包。
somefunction(someobj);
和
somefunction(function(){ return someobj; });
for(;;){
someoperations;
}
和
for(;;)(function(iterator){
someoperations;
})(iterator);
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);
})();
我需要解释在每个测试用例中以第二种方式使用它的优点是什么。
答案 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)。