开发者

What is the difference in these examples of closures?

开发者 https://www.devze.com 2023-03-15 20:58 出处:网络
I have two situations in each testcases. I want to understand the difference and want to understand closures more.

I have two situations in each testcases. I want to understand the difference and want to understand closures more.

test 1:

somefunction(someobj);

and

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

test 2

for(;;){
  someoperations;
}

and

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

test 3:

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

and

开发者_如何学C
(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);
})();

I need an explanation of what is the advantage of using it in the second way in each testcase.


In javascript, the only way to create a new variable scope is in a function.

Whether or not the new scope is needed will depend entirely upon the circumstance. As such, the generic examples you presented don't allow a definitive answer.


To give something more concrete, take we can your test 2, and apply this very common scenario where the someoperations is an asynchronous call like a setTimeout:

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

The trouble is that each function created in the loop (and passed to the setTimeout) references the same i variable, and because it is a setTimeout, which is non-blocking, the loop finishes in its entirety before any of the functions created in the loop are ever invoked.

The result is that each function will alert 4 since that was where the value of i was left after the loop.

Example: http://jsfiddle.net/Ng3rr/


On the other hand, if you invoke a function inside the loop that sets up your setTimeout, passing the value of i to that function, then the variable referenced by each function sent to setTimeout will be the local inner_i, which referenced the value that was passed into that outer invocation.

(I called it inner_i to differentiate between the two, but you could name the inner variable i as well. Doing so is called variable shadowing.)

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

Now each alert displays the value that was received during each iteration.

So as you can see, it depends entirely on the situation.

Example: http://jsfiddle.net/Ng3rr/1/


To add some contrast to the examples above, if we didn't run any asynchronous code in the loop, the outer function would be unnecessary.

This:

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

Example: http://jsfiddle.net/Ng3rr/2/

...and this:

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

Example: http://jsfiddle.net/Ng3rr/3/

...will have identical behavior, making the outer function unnecessary.


So invoking an outer function creates a new variable scope. In that new scope, the variables will be retained by any additional nested functions created in that scope.

Also, while variables created in that scope are accessible in the functions nested in that scope, they're unavailable outside that scope. This keeps you from polluting the surrounding scope with additional variable names.


Let answer without restricting to JavaScript.

There are several ways of using a function as a variable / parameter, one of them is nested inside another function is called a "closure".

You can check a complete description of a "closure" here:

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

I suggest use the separate functions (case 1) for very long extended code, and nested function (case 2) for short code.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号