为什么原生.bind()这么慢?

时间:2015-03-25 08:34:04

标签: google-chrome bind

我最近遇到过这个问题。对于我正在研究的项目,我们过于频繁地使用.bind()方式,考虑到渲染循环只需要16ms来完成任务,它实际上很难达到性能。

所以我做了一些jsperf并注意到调用绑定函数(除了额外的垃圾)比调用未绑定函数或在函数上使用.call要慢。

我真的改变了每一段代码以避免绑定并改为使用.call / .apply。丁这个我不仅产生了较少的功能,而且还提高了我的应用程序的性能。

但是,我对此并不满意,并编写了一种新的绑定函数的方法。 https://github.com/SebastianNette/FastBind

这是使用.call / .apply方法覆盖本机绑定方法。 它的运行速度提高了96%。

对nodejs进行一些测试得出以下结果: 调用绑定函数比调用未绑定函数慢20倍。 使用我自己的方法调用绑定函数只需要未绑定调用的2倍。

所以我想知道本机绑定功能有什么问题。为什么它表现得那样?这将是处理该问题的最佳方式。

我的大多数应用代码现在都是这样编写的:

var scope = this;
this.boundFn = function(a,b,c) { return scope.fn(a,b,c); };

甚至

this.callback = fn;
this.context = context;

this.callback.call(this.context);

我更喜欢后者,因为它不会产生任何新功能。但是,有时我只是必须绑定。 (处理程序,计时器等)。

1 个答案:

答案 0 :(得分:0)

我受过教育的猜测是,它会复制您正在使用的对象,但会替换对象的基础原型。现在,它不需要使用页面呈现代码中的通用预编译对象,而是需要做两件事:

传递的变量即将到来。分析它,克隆它。然后将要调用的指定函数注入新对象。然后在新对象中执行该函数。之后如果不再叫它清理它。

对象具有更复杂和更多的范围循环,绑定将花费很长时间,因为引擎需要遍历所有函数和参数的范围树以查看需要复制的内容。

您已经在使用范围,我强烈建议。内存强度较低,引擎无需复制对象,然后调用函数。而且您可以获得额外的好处,即可以从两个对象访问属性。

根据我的经验,从未真正需要绑定。只需使用setter和getter作为属性,否则作用域变量并不总是在主对象中更改。

以此片段为例

function domagic() {
    this.myproperty = "Hello ";
  }
domagic.prototype = {
  perform:function(){
    var that = this;
    var hello = "World";
    setTimeout(function(){
                         // this in this contect is whatever runs timeout. not domagic
                         // I use this for jQuery and my own objects to get best
                         // of both worlds, but I always post a comment in a scope 
                         // to remind myself what this and that refers to.
                         window.alert(that.myproperty+hello);
                         that.set("Goodbye ");
                         },2000);
  },
  set : function(what) {
    this.myproperty = what;
  }
};
magic = new domagic();
magic.perform();
setTimeout(function(){magic.perform();},2000);