【问题标题】:Difference between Function Binding and Closure in Javascript?Javascript中函数绑定和闭包的区别?
【发布时间】:2015-07-06 11:04:39
【问题描述】:

当我们需要使用当前上下文对象调用 javascript 函数时,我看到有两个选项:

  1. 使用函数绑定
  2. 使用 Javascript 闭包

函数绑定示例

myProject.prototype.makeAjax = function() {
  $.get('http://www.example.com/todoItems', function success(items) {
   this.addItemsToList(items)
  }.bind(this));
}

JS 闭包示例

myProject.prototype.makeAjax = function() {
  var that = this;

  $.get('http://www.example.com/todoItems', function success(items) {
   that.addItemsToList(items)
  });
}

我想问:

  1. 两者哪个在性能方面更好?
  2. 编写代码时应该首选哪个?

【问题讨论】:

  • 不确定是谁投票关闭,但我不认为这太宽泛了?最多可以认为第 2 点是主观的,但选择一种方法或另一种方法有具体的理由。
  • @Ian Point 2 也不是主观的。如果一种方法在某些情况下比另一种方法更好,而在其他情况下另一种方法应该回答这个问题。这就是我要找的。虽然我知道两者可以互换使用,但我还是把第 2 点放在一起,以防万一有人补充一些明智的意见
  • 对于所示的特定示例,我认为性能根本不是问题 - 您不会同时进行许多 Ajax 调用,是吗?但是假设在一个循环中有很多使用,我可能会从你个人喜欢的任何一个开始,除非你发现问题,否则不用担心性能。
  • @nnnnnn 这与示例无关。它更多地是关于方法。方法 1 的性能与方法 2 的性能。我只是写了一些虚拟示例。
  • 这里的比较不错:javascript.info/tutorial/binding

标签: javascript function closures bind


【解决方案1】:

这可能有点取决于应该首选哪个。我倾向于使用后者(虽然实际上我更喜欢前者,但是我们使用的一些 3rd 方库限制了它)。我认为选择风格最重要的是保持一致。

prototype.bind 的注意事项是它不受 IE8 及以下版本的支持,这可能会给您带来问题。

我认为性能明智,我希望bind 会稍微慢一些,因为您在那里调用了一个额外的函数,但这可能取决于浏览器优化。不过,当他们的网站回来回答这部分问题时,我会尝试整理一个 jsperf 示例。

更新

似乎 JSPerf 不会很快出现。这是我整理的一个 sn-p,它显示关闭速度更快(假设我做得正确)。关闭速度略高于 7 倍。如果你在控制台打开的情况下运行,你会看到时间。

var limit = 100000;

var a = {
   val: 0,
   do: function(i) { val = i; /* Actually do some work to ensure doesn't get optimised out */ }  
};

var b = {
   myFunc: function(callback) { callback(); /* Function that's going to change this keyword */}   
};



var start = +new Date();

   for(var i = 0; i < limit; i++) {
     b.myFunc(function() {
        this.do(i);
     }.bind(a));
   };

var end =  +new Date();
var diff = end - start;
console.log("bind took " + diff + " ms");

var start = +new Date();

   for(var i = 0; i < limit; i++) {
     var that = a;
     b.myFunc(function() {
        that.do(i);
     });
   };

var end =  +new Date();
var diff = end - start;

console.log("closured took " + diff + " ms");

【讨论】:

  • 好点..据我所知,浏览器会使用函数定义保存当前对象,同时在使用闭包的情况下创建调用堆栈所以不会变慢。
  • 感谢您提供了一个很好的例子。关闭更快的原因可能是另一个函数调用?
  • @blunderboy 其他函数调用?我能看到的唯一其他函数调用是对bind(a) 本身的实际调用,所以我相信它们应该相当接近。
  • 感谢您的精彩回答。您编写了一个不错的小脚本来测试这两种方法的性能。我会尝试收集更多这方面的信息,如果我得到了,我会在这里写下作为替代答案。
猜你喜欢
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 2013-10-14
  • 2015-01-11
  • 2020-06-04
  • 2016-08-03
  • 1970-01-01
  • 2017-05-16
相关资源
最近更新 更多