<?xml version="1.0" encoding="utf-8"?><!-- generator="wordpress/2.0.2" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Comments on: A huge gotcha with Javascript closures and loops</title>
	<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/</link>
	<description>A weblog for Keith Lea and the Joust Project.</description>
	<pubDate>Mon, 15 Mar 2010 20:48:22 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.0.2</generator>

	<item>
		<title>by: Me</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1828</link>
		<pubDate>Tue, 31 Jan 2006 23:45:42 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1828</guid>
					<description>What?  Splintor has given you all the correct answer + solution, yet you continue deliberating?
Listen to what splintor says, he seems to know what he is talking about!</description>
		<content:encoded><![CDATA[<p>What?  Splintor has given you all the correct answer + solution, yet you continue deliberating?<br />
Listen to what splintor says, he seems to know what he is talking about!
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Zed</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1765</link>
		<pubDate>Fri, 13 Jan 2006 01:57:56 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1765</guid>
					<description>How about using eval() to turn x into a numeric literal?</description>
		<content:encoded><![CDATA[<p>How about using eval() to turn x into a numeric literal?
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Dave Herman</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1748</link>
		<pubDate>Sun, 08 Jan 2006 02:42:24 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1748</guid>
					<description>As some others have pointed out, there is nothing going on here that has to do with &quot;joining function objects&quot;. There are two possible reasons why this behavior might be surprising: 1) a misunderstanding of closures, or 2) the fact that `var' declarations in JavaScript get hoisted to the top of their containing funtion.

Point (1) has been pointed out by others such as Greg and anton above. Point (2) is a subtlety of the JavaScript semantics -- though a var declaration may appear to be nested within the body of the for-loop, it is actually implicitly lifted to the entire scope of the enclosing function.

The short story is that the variable `x' in your example is allocated once in the enclosing function and then mutated at each iteration of the loop.

See: http://calculist.blogspot.com/2005/12/gotcha-gotcha.html</description>
		<content:encoded><![CDATA[<p>As some others have pointed out, there is nothing going on here that has to do with &#8220;joining function objects&#8221;. There are two possible reasons why this behavior might be surprising: 1) a misunderstanding of closures, or 2) the fact that `var&#8217; declarations in JavaScript get hoisted to the top of their containing funtion.</p>
<p>Point (1) has been pointed out by others such as Greg and anton above. Point (2) is a subtlety of the JavaScript semantics &#8212; though a var declaration may appear to be nested within the body of the for-loop, it is actually implicitly lifted to the entire scope of the enclosing function.</p>
<p>The short story is that the variable `x&#8217; in your example is allocated once in the enclosing function and then mutated at each iteration of the loop.</p>
<p>See: <a href='http://calculist.blogspot.com/2005/12/gotcha-gotcha.html' rel='nofollow'>http://calculist.blogspot.com/2005/12/gotcha-gotcha.html</a>
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: anton</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1743</link>
		<pubDate>Wed, 04 Jan 2006 22:07:06 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1743</guid>
					<description>Note that this:

  function createFunction(x) {
    return function() { alert(x); }
  }
  ...
  var f = createFunction(x);

...is equivalent to this:

  var f = (function (x) { return function () { alert (x) } })(x);

...which is the same solution that Maarten gave above.  Both demonstrate the correct use of closures in this case, and are not a &quot;workaround&quot;.  The original code is simply based on an error in understanding of what closures are supposed to do.</description>
		<content:encoded><![CDATA[<p>Note that this:</p>
<p>  function createFunction(x) {<br />
    return function() { alert(x); }<br />
  }<br />
  &#8230;<br />
  var f = createFunction(x);</p>
<p>&#8230;is equivalent to this:</p>
<p>  var f = (function (x) { return function () { alert (x) } })(x);</p>
<p>&#8230;which is the same solution that Maarten gave above.  Both demonstrate the correct use of closures in this case, and are not a &#8220;workaround&#8221;.  The original code is simply based on an error in understanding of what closures are supposed to do.
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Greg Travis</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1658</link>
		<pubDate>Fri, 28 Oct 2005 21:37:32 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1658</guid>
					<description>Actually, the behavior described isn't for either of these reasons:

&quot;This problem has to do with the moment variable names are dereferenced, or substituted for the values they represent.&quot; (Maarten)

&quot;If the values of the varaibles defined in the scope change after the nested function is defined, invocations of the nested function will see the modified value.&quot; (David Flanagan)

In a proper closure, such as the ones you find in Scheme, a closure *should* see changes made to a variable that has been closed over.  But that isn't the problem here.  The problem here is that the &quot;var&quot; statement doesn't create a new location.  Thus,

var shared = 666;
for (var i=0; i</description>
		<content:encoded><![CDATA[<p>Actually, the behavior described isn&#8217;t for either of these reasons:</p>
<p>&#8220;This problem has to do with the moment variable names are dereferenced, or substituted for the values they represent.&#8221; (Maarten)</p>
<p>&#8220;If the values of the varaibles defined in the scope change after the nested function is defined, invocations of the nested function will see the modified value.&#8221; (David Flanagan)</p>
<p>In a proper closure, such as the ones you find in Scheme, a closure *should* see changes made to a variable that has been closed over.  But that isn&#8217;t the problem here.  The problem here is that the &#8220;var&#8221; statement doesn&#8217;t create a new location.  Thus,</p>
<p>var shared = 666;<br />
for (var i=0; i
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Rob</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1444</link>
		<pubDate>Fri, 02 Sep 2005 23:30:56 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1444</guid>
					<description>Comment 11 - that doesn't work!

	var arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
	var fs = [];
	for (var i in arr) {
		var x = arr[i];
		var f = function() { alert(x) };
		fs.push(f);
	}
	for (var j = 0; j </description>
		<content:encoded><![CDATA[<p>Comment 11 - that doesn&#8217;t work!</p>
<p>	var arr = [&#8221;a&#8221;, &#8220;b&#8221;, &#8220;c&#8221;];<br />
	var fs = [];<br />
	for (var i in arr) {<br />
		var x = arr[i];<br />
		var f = function() { alert(x) };<br />
		fs.push(f);<br />
	}<br />
	for (var j = 0; j
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Steve Yen</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1365</link>
		<pubDate>Wed, 10 Aug 2005 17:53:16 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1365</guid>
					<description>Silly textarea -- the above code should be...
&lt;code&gt;
  function loadme() {
    var arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
    var fs = [];
    for (var i in arr) {
      var x = arr[i];
      var f = function() { alert(x) };
      fs.push(f);
    }
    for (var j = 0; j &amp;#60; fs.length; j++) {
      if (fs[j] == fs[j - 1]) 
        alert('hey');
    }
  }
&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>Silly textarea &#8212; the above code should be&#8230;<br />
<code><br />
  function loadme() {<br />
    var arr = ["a", "b", "c"];<br />
    var fs = [];<br />
    for (var i in arr) {<br />
      var x = arr[i];<br />
      var f = function() { alert(x) };<br />
      fs.push(f);<br />
    }<br />
    for (var j = 0; j &lt; fs.length; j++) {<br />
      if (fs[j] == fs[j - 1])<br />
        alert('hey');<br />
    }<br />
  }<br />
</code>
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: David Flanagan</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1364</link>
		<pubDate>Wed, 10 Aug 2005 17:51:23 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1364</guid>
					<description>Previous commenters are correct.This doesn't have anything to do with function joining.  I believe that joining is something that matters only to people implementing JavaScript impelementers.  To the rest of us, it should be impossible to tell whether a given implementation does it or not.  (But I'm not sure about that).

Nested functions include a reference to the scope in which they are defined.  But they do not make a copy of that scope. If the values of the varaibles defined in the scope change after the nested function is defined, invocations of the nested function will see the modified value.  This example at my blog
http://www.davidflanagan.com/blog/2005_07.html#000065 shows two different nested functions that share a scope.  One of the nested functions is a property getter and the other is a property setter.  If you call the setter, it changes the value of a variable in the scope.  And that change is visible through the getter function.

Any nested functions created within the same containing function invocation will share the same scope.  This is not what you want in the example you present here.  Your workaround is the correct one: you've got to have a function maker function.  Each separate invocation of this function making function will create a new, independent scope, and therefore the functions it returns will be independent of each other.</description>
		<content:encoded><![CDATA[<p>Previous commenters are correct.This doesn&#8217;t have anything to do with function joining.  I believe that joining is something that matters only to people implementing JavaScript impelementers.  To the rest of us, it should be impossible to tell whether a given implementation does it or not.  (But I&#8217;m not sure about that).</p>
<p>Nested functions include a reference to the scope in which they are defined.  But they do not make a copy of that scope. If the values of the varaibles defined in the scope change after the nested function is defined, invocations of the nested function will see the modified value.  This example at my blog<br />
<a href='http://www.davidflanagan.com/blog/2005_07.html#000065' rel='nofollow'>http://www.davidflanagan.com/blog/2005_07.html#000065</a> shows two different nested functions that share a scope.  One of the nested functions is a property getter and the other is a property setter.  If you call the setter, it changes the value of a variable in the scope.  And that change is visible through the getter function.</p>
<p>Any nested functions created within the same containing function invocation will share the same scope.  This is not what you want in the example you present here.  Your workaround is the correct one: you&#8217;ve got to have a function maker function.  Each separate invocation of this function making function will create a new, independent scope, and therefore the functions it returns will be independent of each other.
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Steve Yen</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1363</link>
		<pubDate>Wed, 10 Aug 2005 17:51:18 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1363</guid>
					<description>I think your createFunction solution IS the solution, and does not conflict with the ECMA spec.

Basically, your solution won't suffer from a function declaration joining optimization.  Also, it's all about (mis?)understanding scope chains and lexical scoping.  The following tweak to loadme(), for example, (when run in firefox) shows no joining is happening, but you instead get a distinct function created every time...

&lt;code&gt;
  function loadme() {
    var arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
    var fs = [];
    for (var i in arr) {
      var x = arr[i];
      var f = function() { alert(x) };
      fs.push(f);
    }
    for (var j = 0; j 

Also, playing language lawyer here on Dom Leonard's quote:

&quot;Browser independant code *may not* rely on obtaining a different,
unjoined function object for *any* function &lt;b&gt;declared&lt;/b&gt; inside another
function&quot;

...It depends on the meaning of what &quot;declared&quot; is.  For example, this is a function declaration...

function f(x) { alert(x) };

But, is this the following a function declaration?  Or just syntactic sugar for new Function()?

  var f = function(x) { alert(x) };

If it's just syntactic sugar and not a real function declaration, then there won't be any joining there.  The syntactic sugar version is a lot more late bound and runtime-oriented, which a compiler can't really predict...

  var f = test ? function(x) { alert(x) } : function(x) { alert(x+1) };

That's certainly not two declarations, just two potential runtime function &lt;b&gt;creations&lt;/b&gt;, right?

Also, from the Leonard quote:

  &quot;join operations retain differences in the scope chain&quot;

Even IF there was a joining optimization, the interpreter must still track the different scope chains.  So, still, there's no problem and your solution is the right one.

So, in too many bloated words, Erik's right.&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>I think your createFunction solution IS the solution, and does not conflict with the ECMA spec.</p>
<p>Basically, your solution won&#8217;t suffer from a function declaration joining optimization.  Also, it&#8217;s all about (mis?)understanding scope chains and lexical scoping.  The following tweak to loadme(), for example, (when run in firefox) shows no joining is happening, but you instead get a distinct function created every time&#8230;</p>
<p><code><br />
  function loadme() {<br />
    var arr = ["a", "b", "c"];<br />
    var fs = [];<br />
    for (var i in arr) {<br />
      var x = arr[i];<br />
      var f = function() { alert(x) };<br />
      fs.push(f);<br />
    }<br />
    for (var j = 0; j </p>
<p>Also, playing language lawyer here on Dom Leonard's quote:</p>
<p>"Browser independant code *may not* rely on obtaining a different,<br />
unjoined function object for *any* function <b>declared</b> inside another<br />
function&#8221;</p>
<p>&#8230;It depends on the meaning of what &#8220;declared&#8221; is.  For example, this is a function declaration&#8230;</p>
<p>function f(x) { alert(x) };</p>
<p>But, is this the following a function declaration?  Or just syntactic sugar for new Function()?</p>
<p>  var f = function(x) { alert(x) };</p>
<p>If it&#8217;s just syntactic sugar and not a real function declaration, then there won&#8217;t be any joining there.  The syntactic sugar version is a lot more late bound and runtime-oriented, which a compiler can&#8217;t really predict&#8230;</p>
<p>  var f = test ? function(x) { alert(x) } : function(x) { alert(x+1) };</p>
<p>That&#8217;s certainly not two declarations, just two potential runtime function <b>creations</b>, right?</p>
<p>Also, from the Leonard quote:</p>
<p>  &#8220;join operations retain differences in the scope chain&#8221;</p>
<p>Even IF there was a joining optimization, the interpreter must still track the different scope chains.  So, still, there&#8217;s no problem and your solution is the right one.</p>
<p>So, in too many bloated words, Erik&#8217;s right.</code>
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: vk</title>
		<link>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1361</link>
		<pubDate>Wed, 10 Aug 2005 07:20:49 +0000</pubDate>
		<guid>http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/#comment-1361</guid>
					<description>The letters &quot;cl&quot; are very heavily to read e.a. in &quot;clearer&quot;. It looks like a &quot;d&quot; in Firefox 1.0.6</description>
		<content:encoded><![CDATA[<p>The letters &#8220;cl&#8221; are very heavily to read e.a. in &#8220;clearer&#8221;. It looks like a &#8220;d&#8221; in Firefox 1.0.6
</p>
]]></content:encoded>
				</item>
</channel>
</rss>
