javascript / jquery范围jQuery.each和normal for循环之间的差异?

时间:2012-07-05 21:29:27

标签: javascript jquery

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

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

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

$.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();
        }
    }
});

2 个答案:

答案 0 :(得分:4)

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

除了把它放在像匿名函数这样的东西之外,没有什么可以做一个像jQuery.each一样的for循环:

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

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

答案 1 :(得分: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);
    })();
}​