以下示例使用for循环中的闭包机制
我确实知道闭包的目的,但我不能说出以下几段代码之间的最佳选择,特别是为什么一个会比另一个更好?
// First case: Closure wraps the ajax call
$('#container').on('click', 'a.log', function (e) {
_t = this;
for (var i = 0; i < 5; i++) {
(function (j) {
$.ajax({
url: "/logger",
context: _t
}).done(function () {
$(this).addClass("done" + j);
});
})(i);
};
});
// -------------------------------------------------------
// Second case :closure wraps the ajax callback function
$('#container').on('click', 'a.log', function (e) {
for (var i = 0; i < 5; i++) {
$.ajax({
url: "/logger",
context: this
}).done(
(function (j) {
return function () {
$(this).addClass("done" + j);
};
})(i)
);
};
});
我希望有人可以解释一下这个问题。
感谢您的关注&amp;花了很多时间。
答案 0 :(得分:1)
方法#1侧重于IEFE用于保留循环迭代变量的事实。你甚至可以把它写在一行上 - 循环的整个主体进入函数:
for (var i=0; i<5; i++) (function(j) {
…
})(i);
方法#2更多地关注IEFE用于在回调闭包范围内提供j
这一事实 - 您可以将其称为(function makeCallback(j){ … })(i);
。
一般情况下,使用更易读的内容。您可能总是希望使用#1,因为它可以更轻松地创建其他闭包。
在这种特定情况下,#1导致错误:您作为context
参数传递给ajax函数的this
value不是您从事件处理程序中预期的那个,但IEFE中的一个 - undefined
(或草率模式下的window
)。你要么想要#2,要么明确地传递它:
for (var i=0; i<5; i++) (function(j) {
…context:this…
}).call(this, i);
// or
for (var i=0; i<5; i++) (function(el, j) {
…context:el…
})(this, i);
答案 1 :(得分:0)
您还可以考虑将立即调用的函数表达式移出到单独的函数中:
$('#container').on('click', 'a.log', function (e) {
for (var i = 0; i < 5; i++) {
doLogging(i, this);
};
});
function doLogging(i, clickedElement) {
$.ajax({
url: "/logger",
context: clickedElement
}).done(function () {
$(clickedElement).addClass("done" + i);
});
}
我认为理解正在发生的事情要容易得多,而且你不必引入新的变量名'j'。
你没有 发送被点击的元素,你可以使用apply()调用doLogging:
doLogging.apply(this, [i]);
在this
内的doLogging()
将引用所点击的元素。