Functions and function scope

  • Revision slug: Talk:JavaScript/Reference/Functions_and_function_scope
  • Revision title: Functions and function scope
  • Revision id: 15469
  • Created:
  • Creator: ben.mcintyre
  • Is current revision? No
  • Comment 43 words added

Revision Content

TODO: add section on this and method binding --Maian 02:45, 19 September 2005 (PDT)

Reorg

Since this page is getting large very fast, I'm planning on creating a category devoted to Core JavaScript 1.5 Reference:Functions that will have the following subcategories:

* ways to create functions (links to Core_JavaScript_1.5_Reference:Objects:Function, Core_JavaScript_1.5_Reference:Statements:function, and Core_JavaScript_1.5_Reference:Operators:Special_Operators:function_Operator)
** Core JavaScript 1.5 Reference:Functions:Function constructor vs. function declaration vs. function expression

Because of name conflicts and for consistency, moving objects page to Core_JavaScript_1.5_Reference:Global Objects, top-level functions to Core_JavaScript_1.5_Reference:Global Functions, and top-level properties to Core_JavaScript_1.5_Reference:Global Properties.

Any comments? Name suggestions?

--Maian 07:04, 8 September 2005 (PDT)

: Yes, this sounds fine. Thanks for your help! --Nickolay 12:11, 8 September 2005 (PDT)

About "Function constructor vs. function declaration vs. function expression" section

I'm going to just criticize it a bit, don't have time to write something better right now --Nickolay 04:00, 6 September 2005 (PDT)

1) The 4th example would better be

var multiply = function f(x, y) { return x * y; }

- to demonstrate the real difference between the function expression and function declaration, which is that function declaration affects the current scope, while function expression does not: alerting f after the above statement would cause a reference error.

Renamed the function name to func_name but feel free to change it to something more sensible. I already mentioned that func names can only be used in the function's body, but I'll clarify that section a bit. --Maian 06:57, 6 September 2005 (PDT)

We should also mention recursion here.

Agreed, though I wonder how many examples we'll need for that. --Maian 06:57, 6 September 2005 (PDT)

2) "static" isn't really a good term, I think, although I admit I don't have a better idea.

Well, I just changed it to "function's name can't be changed". --Maian 06:57, 6 September 2005 (PDT)

3) This doesn't work for me when executed in global scope, rv:1.8b4 Gecko/20050828. Haven't read the spec on it yet:

foo(); function foo() {alert('FOO!');}
That's odd. It works on Fx/1.06, IE/6SP2, Opera/8.02. In any case, it's part of the ECMAScript spec. Lemme dig it up... It says func declarations are parsed first before running the rest of the script. --Maian 06:57, 6 September 2005 (PDT)
Whoops, that was just the JS Shell I was using. It actually works fine. --Nickolay 08:28, 6 September 2005 (PDT)

4) I don't like using the "precompiled" term, when you actually mean "parsed only once".

I used "compiled" here for consistency, since the "general" subsection right under "description" also uses that term (and who knows where else): "declared functions are compiled". --Maian 06:57, 6 September 2005 (PDT)

5) I think the second list should be unordered, I first thought each item of that list was going to explain the corresponding declaration from the first list.

Agreed. --Maian 06:57, 6 September 2005 (PDT)

6) Should this section, the section about closures, etc. be separated from the main article? That would make it easier to link to them from other articles, and it would also make this article smaller and easier to scan.

Yes, but I don't know where it should be put. TBH, I don't think any of these function specifics should even be under the Function object. It should be put in a totally new chapter. Same thing applies for the method binding section. --Maian 06:57, 6 September 2005 (PDT)
I think we can just put it outside of the JS reference hierarchy. E.g. "Nested functions and closures in JavaScript" --Nickolay 08:28, 6 September 2005 (PDT)
Well, can you tell me what the scope of the reference is? I'm under the impression that anything important about JavaScript that concerns developers should be put there. --Maian 00:29, 7 September 2005 (PDT)
I didn't write it, so I don't know. I think this info is welcome as part of the reference. What I meant was - we are free to name the pages whatever we want. My original intention was to call it "Nested functions and closures in JavaScript", but maybe Core JavaScript Reference:Nested functions and closures would be more consistent with the rest of docs. Dria likes consistency. --Nickolay 02:34, 7 September 2005 (PDT)
But where would it appear on the reference TOC? Well in any case, I'll leave the reorganization to you. --Maian 02:37, 7 September 2005 (PDT)
Now that I think about it, there needs to be section devoted to functions in general. There are three places discussing functions: this section, function statement, and function operator. --Maian 03:45, 7 September 2005 (PDT)

 

Conditionally defining a function

http://developer.mozilla.org/en/docs...ing_a_function

Functions can be conditionally defined using function expressions or the Function constructor. {{ mediawiki.external('quote') }} In the following script, the zero function is never defined and cannot be invoked, because 'if (0)' evaluates to false:

if (0)
   function zero() {
      document.writeln("This is zero.");
   }

If the script is changed so that the condition becomes 'if (1)', function zero is defined.

Note: Although this looks like a function declaration, this is actually a function expression since it is nested within another statement. See differences between function declarations and function expressions. {{ mediawiki.external('/quote') }} Actually, the conditional function may have ambiguous behavior here.

The syntax - if(0) expression - is perfectly legal. An expression cannot start with the function keyword because that might make it ambigous with a FunctionDeclaration.


12.4 Expression Statement

   Syntax
   ExpressionStatement :
       [lookahead ∉ {{, function}] Expression ;
   Note that an ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. Also, an ExpressionStatement cannot start with the function keyword because that might make it ambiguous with a FunctionDeclaration.

-- Garrett

About "Specifying an event handler with a Function object"

This section should be moved down to the example section and revised. The JS reference should be as DOM-independent as possible (with the exception of alert and window). Also, I think the "onEvent" naming has lost favor and should simply be called the "event" event, e.g. "onFocus" => "focus", to comply with the naming conventions set by DOM2 Events. --Maian 07:11, 6 September 2005 (PDT)

Name conflicts

Where I noticed name conflicts myself was when I was calling another function within a for (i=0;etc..) loop, and the function in question was using a for (i=0;etc..) loop, and the 2 i's were in conflict with each other. Simple fix was to rename the 2nd i to j instead. Perhaps this is a good example of the hidden pitfalls with using identically named functions?

new Function() vs function(){}

The article states that the code given to new Function() is parsed every time the function is executed and that function constructors should be avoided because of that. I did a few benchmarks (on Firefox 2.0.0.3, Spider Monkey 4.0 I think and Windows XP) and could not reproduce that.

Consider the following:

function test1() {
  var f = function(){ return 1; };
  for (var i = 0; i < 10000; i++) f();
}
function test2() {
  var f = new Function("return 1;");
  for (var i = 0; i < 10000; i++) f();
}
function test3() {
  for (var i = 0; i < 10000; i++) eval("1");
}
function test4() {
  for (var i = 0; i < 10000; i++) (new Function("return 1;"))();
}

test1() is running very fast as expected. test3() and test4() are crawling along, no surprise here either. But test2() which, according to the article, should have a similar speed as test4() or at least test3(), runs on my machine actually as fast as test1(). For me this looks as if code passed in a function constructor is actually parsed once, when the function object is created and not each time it is executed. Which would make sense to me.

Don't get me wrong, I don't want to promote the use of new Function instead of function(){} here. I just want to point out that, if you absolutely have to parse a string as code, new Function() is still a lot more efficient than eval().

Maybe the information in the article is from an old version of Spider Monkey? --Ps 08:05, 12 May 2007 (PDT)

Efficiency considerations: Closures considered harmful???

Because of this inefficiency, avoid closures whenever possible, i.e. avoid nesting functions whenever possible. For example, consider the following example:

function assignOnclick(element) {
  element.onclick = function() {
      this.style.backgroundColor = 'blue';
   };
}

This can be rewritten to avoid the closure. However, the anonymous inner function would need to be named and would no longer be private to assignOnclick:

function assignOnclick(element) {
   element.onclick = element_onclick;
}

function element_onclick() {
   this.style.backgroundColor = 'blue';
}

Please explain to me how the second example is in any way different than the first - except that it pollutes the global namespace with a function that is called by name exactly never.

Of course you create a new function object each time you create a closure. and of course the local variables the closure uses stay as long as the function object exists. But those are the basic rules of object creation and in no way specific to functions. And like every other object, the function object will be garbage collected once it is no longer referenced. I don't see how you can create memory leaks here if you don't try very hard.

IMO, the second example is efficiency-wise even worse than the first. If the object in element happens to be unloaded, the event hander in the first example would be unloaded as well, like it should - but in the second example, it would still stick around, because it is referenced by the unused global property element_onclick.

function outside(x) {
  function inside(y) {
     return x + y;
  }
  return inside;
}
result = outside(3)(5); // returns 8

In this case, the closure of inside is stored in result. Since result is in the global scope, the closure will remain until the script is unloaded (in a browser, this would happen when the page containing the script is closed).

In this example, clearly the result of calling inside() is stored in result, not the function itself. inside() is returned by outside(3), executed with y = 5 and immediately thrown away. In no way it can hog memory here.

I think this whole section is just plain wrong and should be rewritten. It doesn't look for me as if the author had a very deep understanding of closures, I'm sorry. Please comment.--Ps 05:31, 17 May 2007 (PDT)

Yep, the text in this section is partially incorrect. However, I believe there's a closure-related bug in IE, and in general you have to be careful when using closures. Suppose you have
function init() {
  var bigObject = createBigObject();
  var result = bigObject.doSomething();
  gElement.onclick = function() {
    alert(result);
  }
}

Here you keep bigObject alive until the anonymous closure is gone, even though it only needs the result variable from the init() function scope.

Also, at least in earlier versions it was much easier to leak stuff in Gecko this way. For chrome JS leaking examples see this. --Nickolay 06:58, 17 May 2007 (PDT)

<snip>

 

Since the inner function forms a closure, you can call the outer function and specify arguments for both the outer and inner function:

function outside(x) {
   function inside(y) {
      return x + y;
   }
   return inside;
}
result = outside(3)(5); // returns 8

Efficiency considerations
Edit section

Notice how x is preserved when inside is returned. A closure preserves the arguments and variables in all scopes it contains. Since each call provides potentially different arguments, a closure must be created for each call to the outer function. In other words, each call to outside creates a closure. For this reason, closures can use up a lot of memory. The memory can be freed only when the returned inside is no longer accessible. In this case, the closure of inside is stored inresult. Since result is in the global scope, the closure will remain until the script is unloaded (in a browser, this would happen when the page containing the script is closed).

</snip>

I'd be suprised if this is true.
Returning fninside3 = outside(3);
would put the closure in the variable, but surely if an integer result is returned, that's not going to be stored in the return value.  I'd assume the instance would be destroyed (or at least deallocated due to zero references) as soon as the result is returned.

Edit - whoops, just read a duplicate of my post above.  Seems I'm right, so I might tweak the main page to reflect it.  It's a great page apart from a few little gaffes.

Ben McIntyre - 23 Feb 10

Revision Source

<p>TODO: add section on <code>this</code> and method binding --<a href="/User:Maian" title="User:Maian">Maian</a> 02:45, 19 September 2005 (PDT)</p>
<h3 name="Reorg">Reorg</h3>
<p>Since this page is getting large very fast, I'm planning on creating a category devoted to <a href="/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope" title="En/Core_JavaScript_1.5_Reference/Functions_and_function_scope">Core JavaScript 1.5 Reference:Functions</a> that will have the following subcategories:</p>
<ul> <li>general info</li> <li><a href="/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments" title="En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments">Core JavaScript 1.5 Reference:Functions:arguments</a></li> <li>calling functions (also create a call operator page and link to it) <ul> <li><a href="/en/Core_JavaScript_1.5_Reference/Functions/this" title="en/Core_JavaScript_1.5_Reference/Functions/this">Core JavaScript 1.5 Reference:Functions:this</a>: <code>this</code> and method binding</li> </ul> </li>
</ul>
<pre class="eval">* ways to create functions (links to <a href="/en/Core_JavaScript_1.5_Reference/Global_Objects/Function" title="en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Core_JavaScript_1.5_Reference:Objects:Function</a>, <a href="/en/Core_JavaScript_1.5_Reference/Statements/function" title="en/Core_JavaScript_1.5_Reference/Statements/function">Core_JavaScript_1.5_Reference:Statements:function</a>, and <a href="/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/function_Operator" title="en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/function_Operator">Core_JavaScript_1.5_Reference:Operators:Special_Operators:function_Operator</a>)
** <a href="/en/Core_JavaScript_1.5_Reference/Functions/Function_constructor_vs._function_declaration_vs._function_expression" title="en/Core_JavaScript_1.5_Reference/Functions/Function_constructor_vs._function_declaration_vs._function_expression">Core JavaScript 1.5 Reference:Functions:Function constructor vs. function declaration vs. function expression</a>
</pre>
<ul> <li><a href="/en/Core_JavaScript_1.5_Reference/Functions/Nested_functions_and_closures" title="en/Core_JavaScript_1.5_Reference/Functions/Nested_functions_and_closures">Core JavaScript 1.5 Reference:Functions:Nested functions and closures</a></li>
</ul>
<p>Because of name conflicts and for consistency, moving objects page to <a href="/en/Core_JavaScript_1.5_Reference/Global_Objects" title="en/Core_JavaScript_1.5_Reference/Global_Objects">Core_JavaScript_1.5_Reference:Global Objects</a>, top-level functions to <a href="/en/Core_JavaScript_1.5_Reference/Global_Functions" title="en/Core_JavaScript_1.5_Reference/Global_Functions">Core_JavaScript_1.5_Reference:Global Functions</a>, and top-level properties to <a href="/en/Core_JavaScript_1.5_Reference/Global_Properties" title="en/Core_JavaScript_1.5_Reference/Global_Properties">Core_JavaScript_1.5_Reference:Global Properties</a>.</p>
<p>Any comments? Name suggestions?</p>
<p>--<a href="/User:Maian" title="User:Maian">Maian</a> 07:04, 8 September 2005 (PDT)</p>
<pre class="eval">: Yes, this sounds fine. Thanks for your help! --<a href="/User:Nickolay" title="User:Nickolay">Nickolay</a> 12:11, 8 September 2005 (PDT)
</pre>
<h3 name="About_.22Function_constructor_vs._function_declaration_vs._function_expression.22_section">About "Function constructor vs. function declaration vs. function expression" section</h3>
<p>I'm going to just criticize it a bit, don't have time to write something better right now --<a href="/User:Nickolay" title="User:Nickolay">Nickolay</a> 04:00, 6 September 2005 (PDT)</p>
<p>1) The 4th example would better be</p>
<pre class="eval">var multiply = function f(x, y) { return x * y; }
</pre>
<p>- to demonstrate the real difference between the function expression and function declaration, which is that function declaration affects the current scope, while function expression does not: alerting <code>f</code> after the above statement would cause a reference error.</p>
<dl> <dd>Renamed the function name to func_name but feel free to change it to something more sensible. I already mentioned that func names can only be used in the function's body, but I'll clarify that section a bit. --<a href="/User:Maian" title="User:Maian">Maian</a> 06:57, 6 September 2005 (PDT)</dd>
</dl>
<p>We should also mention recursion here.</p>
<dl> <dd>Agreed, though I wonder how many examples we'll need for that. --<a href="/User:Maian" title="User:Maian">Maian</a> 06:57, 6 September 2005 (PDT)</dd>
</dl>
<p>2) "static" isn't really a good term, I think, although I admit I don't have a better idea.</p>
<dl> <dd>Well, I just changed it to "function's name can't be changed". --<a href="/User:Maian" title="User:Maian">Maian</a> 06:57, 6 September 2005 (PDT)</dd>
</dl>
<p>3) This doesn't work for me when executed in global scope, rv:1.8b4 Gecko/20050828. Haven't read the spec on it yet:</p>
<pre class="eval">foo(); function foo() {alert('FOO!');}
</pre>
<dl> <dd>That's odd. It works on Fx/1.06, IE/6SP2, Opera/8.02. In any case, it's part of the ECMAScript spec. Lemme dig it up... <a class="external" href="http://bclary.com/2004/11/07/ecma-262#a-14"></a> It says func declarations are parsed first before running the rest of the script. --<a href="/User:Maian" title="User:Maian">Maian</a> 06:57, 6 September 2005 (PDT)</dd>
</dl>
<dl> <dd> <dl> <dd>Whoops, that was just the JS Shell I was using. It actually works fine. --<a href="/User:Nickolay" title="User:Nickolay">Nickolay</a> 08:28, 6 September 2005 (PDT)</dd> </dl> </dd>
</dl>
<p>4) I don't like using the "precompiled" term, when you actually mean "parsed only once".</p>
<dl> <dd>I used "compiled" here for consistency, since the "general" subsection right under "description" also uses that term (and who knows where else): "declared functions are compiled". --<a href="/User:Maian" title="User:Maian">Maian</a> 06:57, 6 September 2005 (PDT)</dd>
</dl>
<p>5) I think the second list should be unordered, I first thought each item of that list was going to explain the corresponding declaration from the first list.</p>
<dl> <dd>Agreed. --<a href="/User:Maian" title="User:Maian">Maian</a> 06:57, 6 September 2005 (PDT)</dd>
</dl>
<p>6) Should this section, the section about closures, etc. be separated from the main article? That would make it easier to link to them from other articles, and it would also make this article smaller and easier to scan.</p>
<dl> <dd>Yes, but I don't know where it should be put. TBH, I don't think any of these function specifics should even be under the Function object. It should be put in a totally new chapter. Same thing applies for the <a href="/en/Core_JavaScript_1.5_Reference/Operators/Member_Operators" title="en/Core_JavaScript_1.5_Reference/Operators/Member_Operators">method binding</a> section. --<a href="/User:Maian" title="User:Maian">Maian</a> 06:57, 6 September 2005 (PDT)</dd>
</dl>
<dl> <dd> <dl> <dd>I think we can just put it outside of the JS reference hierarchy. E.g. "Nested functions and closures in JavaScript" --<a href="/User:Nickolay" title="User:Nickolay">Nickolay</a> 08:28, 6 September 2005 (PDT)</dd> </dl> </dd>
</dl>
<dl> <dd> <dl> <dd> <dl> <dd>Well, can you tell me what the scope of the reference is? I'm under the impression that anything important about JavaScript that concerns developers should be put there. --<a href="/User:Maian" title="User:Maian">Maian</a> 00:29, 7 September 2005 (PDT)</dd> </dl> </dd> </dl> </dd>
</dl>
<dl> <dd> <dl> <dd> <dl> <dd> <dl> <dd>I didn't write it, so I don't know. I think this info is welcome as part of the reference. What I meant was - we are free to name the pages whatever we want. My original intention was to call it "Nested functions and closures in JavaScript", but maybe <a href="/en/Core_JavaScript_Reference/Nested_functions_and_closures" title="en/Core_JavaScript_Reference/Nested_functions_and_closures">Core JavaScript Reference:Nested functions and closures</a> would be more consistent with the rest of docs. Dria likes consistency. --<a href="/User:Nickolay" title="User:Nickolay">Nickolay</a> 02:34, 7 September 2005 (PDT)</dd> </dl> </dd> </dl> </dd> </dl> </dd>
</dl>
<dl> <dd> <dl> <dd> <dl> <dd> <dl> <dd> <dl> <dd>But where would it appear on the reference TOC? Well in any case, I'll leave the reorganization to you. --<a href="/User:Maian" title="User:Maian">Maian</a> 02:37, 7 September 2005 (PDT)</dd> </dl> </dd> </dl> </dd> </dl> </dd> </dl> </dd>
</dl>
<dl> <dd> <dl> <dd> <dl> <dd> <dl> <dd> <dl> <dd> <dl> <dd>Now that I think about it, there needs to be section devoted to functions in general. There are three places discussing functions: this section, function statement, and function operator. --<a href="/User:Maian" title="User:Maian">Maian</a> 03:45, 7 September 2005 (PDT)</dd> </dl> </dd> </dl> </dd> </dl> </dd> </dl> </dd> </dl> </dd>
</dl>
<p> </p>
<pre class="eval">Conditionally defining a function
</pre>
<p><a class=" external" href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Functions#Conditionally_defining_a_function" rel="freelink">http://developer.mozilla.org/en/docs...ing_a_function</a></p>
<p>Functions can be conditionally defined using function expressions or the Function constructor. {{ mediawiki.external('quote') }} In the following script, the zero function is never defined and cannot be invoked, because 'if (0)' evaluates to false:</p>
<pre>if (0)
   function zero() {
      document.writeln("This is zero.");
   }
</pre>
<p>If the script is changed so that the condition becomes 'if (1)', function zero is defined.</p>
<p>Note: Although this looks like a function declaration, this is actually a function expression since it is nested within another statement. See differences between function declarations and function expressions. {{ mediawiki.external('/quote') }} Actually, the conditional function may have ambiguous behavior here.</p>
<p>The syntax - if(0) expression - is perfectly legal. An expression cannot start with the function keyword because that might make it ambigous with a FunctionDeclaration.</p>
<p><br>
12.4 Expression Statement</p>
<pre class="eval">   Syntax
</pre>
<pre class="eval">   ExpressionStatement :
       [lookahead ∉ {{, function}] Expression ;
</pre>
<pre class="eval">   Note that an ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. Also, an ExpressionStatement cannot start with the function keyword because that might make it ambiguous with a FunctionDeclaration.
</pre>
<p>-- Garrett</p>
<h3 name="About_.22Specifying_an_event_handler_with_a_Function_object.22">About "Specifying an event handler with a Function object"</h3>
<p>This section should be moved down to the example section and revised. The JS reference should be as DOM-independent as possible (with the exception of <code>alert</code> and <code>window</code>). Also, I think the "onEvent" naming has lost favor and should simply be called the "event" event, e.g. "onFocus" =&gt; "focus", to comply with the naming conventions set by DOM2 Events. --<a href="/User:Maian" title="User:Maian">Maian</a> 07:11, 6 September 2005 (PDT)</p>
<h3 name="Name_conflicts">Name conflicts</h3>
<p>Where I noticed name conflicts myself was when I was calling another function within a for (i=0;etc..) loop, and the function in question was using a for (i=0;etc..) loop, and the 2 i's were in conflict with each other. Simple fix was to rename the 2nd i to j instead. Perhaps this is a good example of the hidden pitfalls with using identically named functions?</p>
<h3 name="new_Function.28.29_vs_function.28.29{}"><code>new Function()</code> vs <code>function(){}</code></h3>
<p>The article states that the code given to <code>new Function()</code> is parsed <em>every time the function is executed</em> and that function constructors should be avoided because of that. I did a few benchmarks (on Firefox 2.0.0.3, Spider Monkey 4.0 I think and Windows XP) and could not reproduce that.</p>
<p>Consider the following:</p>
<pre class="eval">function test1() {
  var f = function(){ return 1; };
  for (var i = 0; i &lt; 10000; i++) f();
}
</pre>
<pre class="eval">function test2() {
  var f = new Function("return 1;");
  for (var i = 0; i &lt; 10000; i++) f();
}
</pre>
<pre class="eval">function test3() {
  for (var i = 0; i &lt; 10000; i++) eval("1");
}
</pre>
<pre class="eval">function test4() {
  for (var i = 0; i &lt; 10000; i++) (new Function("return 1;"))();
}
</pre>
<p><code>test1()</code> is running very fast as expected. <code>test3()</code> and <code>test4()</code> are crawling along, no surprise here either. But <code>test2()</code> which, according to the article, should have a similar speed as <code>test4()</code> or at least <code>test3()</code>, runs on my machine actually as fast as <code>test1()</code>. For me this looks as if code passed in a function constructor is actually parsed <em>once</em>, when the function object is created and not each time it is executed. Which would make sense to me.</p>
<p>Don't get me wrong, I don't want to promote the use of <code>new Function</code> instead of <code>function(){}</code> here. I just want to point out that, if you absolutely <em>have</em> to parse a string as code, <code>new Function()</code> is still a lot more efficient than <code>eval()</code>.</p>
<p>Maybe the information in the article is from an old version of Spider Monkey? --<a href="/User:Ps" title="User:Ps">Ps</a> 08:05, 12 May 2007 (PDT)</p>
<h3 name="Efficiency_considerations:_Closures_considered_harmful.3F.3F.3F">Efficiency considerations: Closures considered harmful???</h3>
<p><em>Because of this inefficiency, avoid closures whenever possible, i.e. avoid nesting functions whenever possible. For example, consider the following example:</em></p>
<pre class="eval">function assignOnclick(element) {
  element.onclick = function() {
      this.style.backgroundColor = 'blue';
   };
}

</pre>
<p><em>This can be rewritten to avoid the closure. However, the anonymous inner function would need to be named and would no longer be private to assignOnclick:</em></p>
<pre class="eval">function assignOnclick(element) {
   element.onclick = element_onclick;
}

function element_onclick() {
   this.style.backgroundColor = 'blue';
}
</pre>
<p>Please explain to me how the second example is in any way different than the first - except that it pollutes the global namespace with a function that is called by name exactly never.</p>
<p>Of course you create a new function object each time you create a closure. and of course the local variables the closure uses stay as long as the function object exists. But those are the basic rules of object creation and in no way specific to functions. And like every other object, the function object will be garbage collected once it is no longer referenced. I don't see how you can create memory leaks here if you don't try <em>very</em> hard.</p>
<p>IMO, the second example is efficiency-wise even worse than the first. If the object in <code>element</code> happens to be unloaded, the event hander in the first example would be unloaded as well, like it should - but in the second example, it would still stick around, because it is referenced by the unused global property <code>element_onclick</code>.</p>
<pre class="eval">function outside(x) {
  function inside(y) {
     return x + y;
  }
  return inside;
}
result = outside(3)(5); // returns 8
</pre>
<p><em>In this case, the closure of inside is stored in result. Since result is in the global scope, the closure will remain until the script is unloaded (in a browser, this would happen when the page containing the script is closed).</em></p>
<p>In this example, clearly the <em>result</em> of calling <code>inside()</code> is stored in <code>result</code>, not the function itself. <code>inside()</code> is returned by <code>outside(3)</code>, executed with y = 5 and immediately thrown away. In no way it can hog memory here.</p>
<p>I think this whole section is just plain wrong and should be rewritten. It doesn't look for me as if the author had a very deep understanding of closures, I'm sorry. Please comment.--<a href="/User:Ps" title="User:Ps">Ps</a> 05:31, 17 May 2007 (PDT)</p>
<dl> <dd>Yep, the text in this section is partially incorrect. However, I believe there's a closure-related bug in IE, and in general you have to be careful when using closures. Suppose you have</dd>
</dl>
<pre class="eval">function init() {
  var bigObject = createBigObject();
  var result = bigObject.doSomething();
  gElement.onclick = function() {
    alert(result);
  }
}
</pre>
<p>Here you keep <code>bigObject</code> alive until the anonymous closure is gone, even though it only needs the <code>result</code> variable from the <code>init()</code> function scope.</p>
<p>Also, at least in earlier versions it was much easier to leak stuff in Gecko this way. For chrome JS leaking examples see <a class="external" href="http://www.mozilla.org/scriptable/avoiding-leaks.html">this</a>. --<a href="/User:Nickolay" title="User:Nickolay">Nickolay</a> 06:58, 17 May 2007 (PDT)</p>
<p>&lt;snip&gt;</p>
<p> </p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.7em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">Since the inner function forms a closure, you can call the outer function and specify arguments for both the outer and inner function:</p>
<pre class="eval" style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.7em; margin-left: 0px; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(223, 236, 241); border-right-color: rgb(223, 236, 241); border-bottom-color: rgb(223, 236, 241); border-left-color: rgb(223, 236, 241); overflow-x: auto; overflow-y: auto; font: normal normal normal 12px/normal 'Courier New', 'Andale Mono', monospace; color: rgb(37, 34, 29); ">function outside(x) {
   function inside(y) {
      return x + y;
   }
   return inside;
}
result = outside(3)(5); // returns 8
</pre>
<div id="section_11">
<h4 class="editable" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: normal; font-family: Georgia, 'Times New Roman', Times, serif; color: rgb(43, 39, 32); font-size: 18px; "><span>Efficiency considerations</span>
<div class="editIcon" style="display: inline; visibility: hidden; margin-left: 4px; font-size: 11px; font-weight: normal; "><a href="/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope#" style="text-decoration: none; color: rgb(4, 121, 167); visibility: hidden; " title="Edit section"><span class="icon" style="height: 16px; overflow-x: hidden; overflow-y: hidden; "><img alt="Edit section" class="sectionedit" src="/skins/common/icons/icon-trans.gif"></span></a></div>
</h4>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.7em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">Notice how <code style="color: rgb(37, 34, 29); font-weight: inherit; ">x</code> is preserved when <code style="color: rgb(37, 34, 29); font-weight: inherit; ">inside</code> is returned. A closure preserves the arguments and variables in all scopes it contains. Since each call provides potentially different arguments, a closure must be created for each call to the outer function. In other words, each call to <code style="color: rgb(37, 34, 29); font-weight: inherit; ">outside</code> creates a closure. For this reason, closures can use up a lot of memory. The memory can be freed only when the returned <code style="color: rgb(37, 34, 29); font-weight: inherit; ">inside</code> is no longer accessible. In this case, the closure of <code style="color: rgb(37, 34, 29); font-weight: inherit; ">inside</code> is stored in<code style="color: rgb(37, 34, 29); font-weight: inherit; ">result</code>. Since <code style="color: rgb(37, 34, 29); font-weight: inherit; ">result</code> is in the global scope, the closure will remain until the script is unloaded (in a browser, this would happen when the page containing the script is closed).</p>
</div>
<p>&lt;/snip&gt;</p>
<p>I'd be suprised if this is true.<br>
Returning fninside3 = outside(3); <br>
would put the closure in the variable, but surely if an integer result is returned, that's not going to be stored in the return value.  I'd assume the instance would be destroyed (or at least deallocated due to zero references) as soon as the result is returned.</p>
<p>Edit - whoops, just read a duplicate of my post above.  Seems I'm right, so I might tweak the main page to reflect it.  It's a great page apart from a few little gaffes.</p>
<p>Ben McIntyre - 23 Feb 10</p>
Revert to this revision