两种使用闭包的方式之间的区别

时间:2014-04-11 10:16:38

标签: javascript jquery closures

以下示例使用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;花了很多时间。

2 个答案:

答案 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()将引用所点击的元素。