Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Considering that <code>var</code> declarations have function scope (or global if declared in the global scope), your code is equivalent to:</p> <pre><code>var tempS = shapes.slice(), i, S; for (i = 0; i &lt; shapes.length; i++) { S = tempS.pop(); if (S.name == 'pieChart') { document.getElementById(S.id).addEventListener('mousedown', function (e) { alert(S.id); }, false); } } </code></pre> <p>Now, it is clear that <code>S</code> is scoped outside of the <code>for</code> block, and as the event handlers will be triggered after the loop finishes, <code>S</code> will have the value of the last iteration.</p> <p>You need to create a new scope, either through a callback factory (as in this <a href="https://stackoverflow.com/a/750506/1331430">related answer</a>) or an <a href="http://benalman.com/news/2010/11/immediately-invoked-function-expression/" rel="nofollow noreferrer">IIFE</a>, to trap the current <code>S</code> value of the iteration.</p> <pre><code>var tempS = shapes.slice(); for (var i = 0; i &lt; shapes.length; i++) { (function() {//introduces a new scope var S = tempS.pop(); //now S is scoped inside this iteration's IIFE if (S.name == 'pieChart') { document.getElementById(S.id).addEventListener('mousedown', function (e) { alert(S.id); //will reference the IIFE scope's S }, false); } }()); } </code></pre> <p>You can do this in many alternative ways as well, for example, using <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach" rel="nofollow noreferrer">Array#forEach</a>:</p> <pre><code>var tempS = shapes.slice(); shapes.forEach(function(S) { //S is now scoped in the forEach callback scope if (S.name == 'pieChart') { document.getElementById(S.id).addEventListener('mousedown', function (e) { alert(S.id); }, false); } }); </code></pre> <p>Note that this will change the iteration order, but I believe it won't matter for this use case.</p> <hr> <p>In ES6 it will be possible to use <code>let</code> to create block-scoped variables:</p> <pre><code>for (var i = 0; i &lt; shapes.length; i++) { let S = tempS.pop(); //scoped inside the `for` block if (S.name == 'pieChart') { document.getElementById(S.id).addEventListener('mousedown', function (e) { alert(S.id); }, false); } } </code></pre> <p>I'm leaving this approach here for future readers, as <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let" rel="nofollow noreferrer"><code>let</code></a> is not ready for production yet. Most recent browsers do have experimental implementations though (see <a href="http://kangax.github.io/es5-compat-table/es6/" rel="nofollow noreferrer">ES6 compat table</a>).</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload