这里有趣的问题,优化了一些代码,但是使用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();
}
}
});
答案 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);
})();
}