简体   繁体   English

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

[英]javascript / jquery scope differences between jQuery.each and normal for loop?

Interesting issue here, optimising some code but am having trouble with scope issues using a javascript loop as opposed to a jQuery loop. 这里有趣的问题是,优化了一些代码,但是使用javascript循环而不是jQuery循环遇到范围问题。

If for example we have 3 "decade" iterations, with values "1950", "1960", and "1970", using the javascript loop, we would get "1970" (the last iteration in the loop) all the time on the "alert" of decade.name, but using jQuery.each we get the expected value for each created element. 例如,如果使用javascript循环,我们进行了3次“十年”迭代,其值分别为“ 1950”,“ 1960”和“ 1970”,则我们将始终获得“ 1970”(循环中的最后一次迭代) decade.name的“警报”,但是使用jQuery.each,我们获得每个创建的元素的期望值。

Questions: - why does this work with jQuery.each and not regular javascript loop? 问题:-为什么此方法适用于jQuery.each而不是常规javascript循环? - how can i make this work with a normal javascript for loop? -如何使用普通的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();
        }
    }
});

jQuery.each is a function, and Javascript functions are scoped automatically, ie when they go away, so do all the variables within them. jQuery.each是一个函数,并且Javascript函数会自动确定范围,即当它们消失时,它们中的所有变量也会自动作用域。 Pure Javascript for loops, however, are not scoped because it's a flow control -- it looks like a contained unit, but it's no different in principle than any other keyword or statement. 但是,纯Javascript for循环没有作用域,因为它是一个流控制-它看起来像一个包含的单元,但在原理上与任何其他关键字或语句都没有不同。

There's nothing that can be done to make a for loop scoped like jQuery.each other than putting it within something like an anonymous function: 除了将其放入匿名函数之内之外,没有其他任何方法可以使for循环的作用域类似于jQuery.each

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

But that doesn't really change the behavior of the for loop, it just encapsulates the namespace so nothing survives after the anonymous function (and the for loop inside) executes. 但这并没有真正改变for循环的行为,它只是封装了名称空间,因此在执行匿名函数(以​​及内部的for循环)之后,任何内容都无法保留。

Consider the following sample: http://jsfiddle.net/9vZUg/1/ 考虑以下示例: 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);
}​

That happens because we create function at one point but use it later on. 发生这种情况是因为我们在某一时刻创建了函数,但稍后再使用它。 And at the moment we are calling it year is always 2012 as it was on the last iteration. 现在,我们称年份始终是2012年,就像上一次迭代一样。 How can we fix it? 我们该如何解决? Create closure: 创建关闭:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM