开发者

Sticky/static variable references in for loops

In this example I create three buttons 'one' 'two' 'three'. When clicked I want them to alert their number:

<html>
    <head>
        <script type="application/javascript" src="jquery.js"></script>
        <script type="application/javascript">
            $(document).ready(function() {
                var numbers = ['one', 'two', 'three'];
                for (i in numbers) {
                    var nr = numbers[i];
                    var li = $('<li>' + nr + '</li>');
                    li.click(function() {
                        var newVariable = String(nr);
                        alert(i); // 2
                        alert(nr); // three
           开发者_JS百科             alert(newVariable); // three
                        alert(li.html()); // three
                    });
                    $('ul').append(li);
                }
            });
        </script>
    </head>
    <body>
        <ul>
        </ul>
    </body>
</html>

The problem is, when any of these are clicked, the last value of the loop's variables is used, i.e. alert box always says 'three'.

In JavaScript, variables inside for-loops seem to be 'static' in the C language sense. Is there some way to create separate variables for each click function, i.e. not using the same reference?

Thanks!

Edit:

The solution is to use jQuery.data to associate arbitrary data with each element:

<html>
    <head>
        <script type="application/javascript" src="jquery.js"></script>
        <script type="application/javascript">
            $(document).ready(function() {
                var numbers = ['one', 'two', 'three'];
                for (i in numbers) {
                    var nr = numbers[i];
                    var li = $('<li>' + nr + '</li>');
                    li.data('nr', nr);
                    li.click(function() {
                        alert($(this).data('nr'));
                    });
                    $('ul').append(li);
                }
            });
        </script>
    </head>
    <body>
        <ul>
        </ul>
    </body>
</html>


Alternately, place a closure inside the for loop.

        $(document).ready(function() {
            var numbers = ['one', 'two', 'three'];
            for (i in numbers) {
                (function () {
                var nr = numbers[i];
                var li = $('<li>' + nr + '</li>');

                li.click(function() {
                    var newVariable = String(nr);
                    alert(i); // 2
                    alert(nr); // three
                    alert(newVariable); // three
                    alert(li.html()); // three
                });

                $('ul').append(li);

                }());
            }
        });

It's also bad practise for using for in for iterating over an array. It should be strictly used for iterating over object fields. Use the for(;;;) instead.


You need to attach any data on the elements or on http://api.jquery.com/jQuery.data/ in order to reuse later on.

e.g

...
var li = $('<li>' + nr + '</li>');
jQuery.data(li, "the-value", foo);
li.click(function() {
    var foo = jQuery.data(li, "the-value");
    ...
}


This is working as it should, you are asking the click event to use these variables (not absolute values) and by the time the method is called the variables are at their 'max' values.

Try using the title attribute to store the value you want to return, i.e.:

var li = $('<li title="' + nr + '">' + nr + '</li>');

Then your alert would be:

alert(this.attr('title'));

Not tested but that should work or at least set you on the right track.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜