2

这里有一个有趣的问题,优化了一些代码,但在使用 javascript 循环而不是 jQuery 循环时遇到了范围问题。

例如,如果我们有 3 次“十年”迭代,其值为“1950”、“1960”和“1970”,使用 javascript 循环,我们将一直得到“1970”(循环中的最后一次迭代) “alert”的decade.name,但使用jQuery.each 我们得到每个创建元素的预期值。

问题: - 为什么这适用于 jQuery.each 而不是常规的 javascript 循环?- 我怎样才能使用普通的 javascript for 循环来完成这项工作?

$.ajax({
    async: true,
    type: 'post',
    url: 'ajax/products.php',
    data: {
        'action': 'get_filter_decades',
        'data': {
            "search_term": ple.find('input[name="search_term"]').val(),
            "first_letter": $.bbq.getState('first_letter'),
            "category_id": categoryId.val(),
            "original_release_year_range": ple.find('input[name="original_release_year_range"]').val()
        }
    },
    success: function (jsonResponse) {
        if (jsonObj = handleJsonResponse(jsonResponse)) {
            var filterDecadesResultList = filterDecades.find('ul.decade_result_list');
            filterDecadesResultList.hide();
            filterDecadesResultList.empty();

            var originalReleaseYearRange =     $(ple.find('input[name="original_release_year_range"]'));

            // jquery loop
            //$( jsonObj.data.decades ).each( function( i, decade ) {

            // javascript loop (faster!)
            var decadesLength = jsonObj.data.decades.length;
            var listElement;
            var linkElement;
            var decade;

            for (var i = 0; i < decadesLength; i++) {
                decade = jsonObj.data.decades[i];
                listElement = $('<li />');
                linkElement = $('<a />');
                linkElement.text(decade.name);

                if (decade.product_count > 0) {
                    linkElement.append(' (' + decade.product_count + ')');
                    if (decade.selected) {
                        linkElement.addClass('selected');
                    }
                    linkElement.on("click", function () {
                        alert(decade.name);

                        if (!linkElement.hasClass('selected')) {
                            originalReleaseYearRange.val(decade.name);
                            $.bbq.pushState({
                                'original_release_year_range': decade.name
                            });
                            productListPaginate(ple);
                        } else {
                            originalReleaseYearRange.val('');
                            $.bbq.removeState('original_release_year_range');
                            productListPaginate(ple);
                        }
                    });
                }

                listElement.append(linkElement);
                filterDecades.find('ul.decade_result_list').append(listElement);
                // jquery loop
                //});

                // javascript loop
            }

            filterDecadesResultList.show();
        }
    }
});
4

2 回答 2

4

jQuery.each是一个函数,并且Javascript函数是自动作用域的,即当它们消失时,它们中的所有变量也是如此。然而,纯 Javascript for 循环没有作用域,因为它是一个流控制——它看起来像一个包含的单元,但原则上它与任何其他关键字或语句没有什么不同。

jQuery.each除了将它放在像匿名函数之类的东西中之外,没有什么可以做的事情来使 for 循环范围更广:

(function(){
    for (i=0; i<10; i++) {
        // do something
    }
})();

但这并没有真正改变 for 循环的行为,它只是封装了命名空间,因此在匿名函数(以​​及内部的 for 循环)执行后没有任何东西可以存活。

于 2012-07-05T21:41:23.797 回答
3

考虑以下示例:http: //jsfiddle.net/9vZUg/1/

var years = [2010, 2011, 2012];
for (var i=0; i<years.length; i++) {
    var year = years[i];
    var input = document.createElement("input");
    input.type = "button";
    input.value = year;
    input.onclick = function(){
        alert(year); // at this point year will be always be 2012
    }
    document.body.appendChild(input);
}​

发生这种情况是因为我们在某一时刻创建了函数,但稍后再使用它。目前我们称它为 2012 年,就像上一次迭代一样。我们该如何解决?创建闭包:

var years = [2010, 2011, 2012];
for (var i=0; i<years.length; i++) {
    (function(){
        var year = years[i];
        var input = document.createElement("input");
        input.type = "button";
        input.value = year;    
        // now year is stored here and would be unique for each handler
        input.onclick = function(){
            alert(year);
        }
        document.body.appendChild(input);
    })();
}​
于 2012-07-05T21:47:14.707 回答