Why did javascript code inside loop work once the code was extracted to a separate function?
<p>I had the following code in a jQuery plugin I was writing to make a tag cloud. I'm passing in a an array of data in the format [{tag: "028", count: 15}, {tag: "101", count: 357}]. I'm creating the cloud as spans for now, normalizing the size based on the count. The spans are created properly, i.e. they have the correct size and text. I added a couple of events, click and mouse events. No matter what span is clicked on, it always shows me the alert for the last element in the array. </p>

<p>While trying to debug what was going on, I extracted the element creation code to a seperate function. Once I did that, the click event worked properly, i.e. the click event shows the correct data for what span was clicked. </p>

<p>I assumed that both versions would produce the same results. Why did the click event work once I extracted the element creation to it's own function?</p>

<p>This is the version that did NOT work:</p>

<pre><code>for (var i = 0; i &lt; tagList.length; ++i) {
    if (tagList[i] != null) {
        var tagValue = tagList[i].tag;
        var tagCount = tagList[i].count;
        var size = getNormalizedSize(tagCount);
        var theSpan = getText(tagValue, tagCount);   // &lt;span style="font-size: {1}em"&gt;{0}&lt;\/span&gt;
        var theAlert = getAlert(tagValue, tagCount); // "Project {0} is has logged in {1} drawings"
        var newElement = $(theSpan);
        newElement.click(function() {
            alert(theAlert);                        // Always shows data from last element in array
        }).mouseenter(function(event) {
            $(this).css('backgroundColor', '#FFC');
        }).mouseleave(function() {
            $(this).css('backgroundColor', '#FFF');
        });
        this.append(newElement).append(" ");
    }
}
</code></pre>

<p>This is the version that worked:</p>

<pre><code>for (var i = 0; i &lt; tagList.length; ++i) {
    if (tagList[i] != null) {
        var tagValue = tagList[i].tag;
        var tagCount = tagList[i].count;
        var tagElem = buildElement(tagValue, tagCount);
        this.append(tagElem).append(" ");
    }
}

function buildElement(tagValue, tagCount) {
    var size = getNormalizedSize(tagCount);
    var theSpan = getText(tagValue, tagCount);   // &lt;span style="font-size: {1}em"&gt;{0}&lt;\/span&gt;
    var theAlert = getAlert(tagValue, tagCount); // "Project {0} is has logged in {1} drawings"
    var newElement = $(theSpan);
    newElement.click(function() {
        alert(theAlert);
    }).mouseenter(function(event) {
        $(this).css('backgroundColor', '#FFC');
    }).mouseleave(function() {
        $(this).css('backgroundColor', '#FFF');
    });
    return newElement;
}
</code></pre>
