我有以下代码,我已简化,$currEl
被记录并正确显示,但在$ .ajax调用中它记录为null
。
我错过了什么吗?
for(var i=0, j = atgSlots.length; i < j; i++) {
var currSlot = atgSlots[i].split('|'),
$currEl = currSlot[0].length ? $('[data-atg-url=' + currSlot[0] + ']') : null,
wcmLocation = currSlot[2] || null;
if ($currEl !== null && wcmLocation !== null) {
console.log($currEl);
$.ajax({
url: wcmLocation,
success: function(html) { console.log($currEl); updateSlots.setContent($currEl, html); },
error: updateSlots.checkDefault
}); // $.ajax
}
} // for : atgSlots
答案 0 :(得分:3)
问题是你的ajax成功函数有一个实时引用 $currEl
变量,而不是 copy ,就像创建函数时一样。因此,所有这些成功处理程序都引用相同的变量,因此引用相同的值 - 循环中分配给$currEl
的最后一个值。这是一个相同效果的简单例子:
var a;
a = "before";
setTimeout(function() {
alert(a);
}, 10);
a = "after";
警告“之后”而不是“之前”,因为在10ms之后调用的函数使用当前值a
。 See it in action
您可以通过使用中间函数为每个函数提供自己的变量来解决此问题。这是一个极简主义的变化:
for(var i=0, j = atgSlots.length; i < j; i++) {
var currSlot = atgSlots[i].split('|'),
$currEl = currSlot[0].length ? $('[data-atg-url=' + currSlot[0] + ']') : null,
wcmLocation = currSlot[2] || null;
if ($currEl !== null && wcmLocation !== null) {
console.log($currEl);
$.ajax({
url: wcmLocation,
// ==== Change starts here
success: (function($thisEl) {
return function(html) { console.log($thisEl); updateSlots.setContent($thisEl, html); };
})($currEl),
// ==== Change ends here
error: updateSlots.checkDefault
}); // $.ajax
}
} // for : atgSlots
这样做是在每个循环上创建并调用工厂函数,将函数传递给$currEl
的当前值。然后该函数返回应该用作成功处理程序的函数。成功处理程序使用外部上下文中的其他信息(html
,我假设它们应该对所有这些信息都是通用的),但使用$thisEl
(函数参数)而不是$currEl
以这种方式执行它实际上略微效率低,因为我们创建了新工厂函数的多个相同副本。一个不太简约 - 也许更清晰 - 的版本看起来像这样:
for(var i=0, j = atgSlots.length; i < j; i++) {
var currSlot = atgSlots[i].split('|'),
$currEl = currSlot[0].length ? $('[data-atg-url=' + currSlot[0] + ']') : null,
wcmLocation = currSlot[2] || null;
if ($currEl !== null && wcmLocation !== null) {
console.log($currEl);
$.ajax({
url: wcmLocation,
success: buildSuccessHandler($currEl),
error: updateSlots.checkDefault
}); // $.ajax
}
} // for : atgSlots
function buildSuccessHandler($thisEl) {
return function(html) {
console.log($thisEl);
updateSlots.setContent($thisEl, html);
};
}
(我假设所有这些代码都包含在某个函数中。)
有关闭包的更多信息以及此博文中的实时参考资料:"Closures are not complicated"。
答案 1 :(得分:0)
问题可能是当调用AJAX回调时,$ currEl将被设置为不同的值,或者为null,因为它将在调用回调时获取$ currEl的值,而不是在声明AJAX函数时