2015-03-25 118 views
1

我最近遇到這個問題。對於我正在開發的項目,我們經常使用.bind()方法,考慮到渲染循環只有16ms的功能,所以它實際上很難達到性能。爲什麼native .bind()這麼慢?

所以我做了一些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);

我更喜歡後者因爲它不會產生任何新的功能。但是,有時我只是必須綁定。 (處理程序,定時器等)。

+0

'.call'和'.apply'據我瞭解,做了'this'關鍵字的東西相對於非常不同的,和上下文。如果你避免使用'this'關鍵字,那麼你應該沒問題。但是,警告的話,你正在創建的lambda正在創建閉包,如果你不小心的話(這些函數會引用'scope')會泄漏內存。 – Aron 2015-03-25 08:48:34

回答

0

我的教育猜測是它使得你正在使用的對象的克隆,但取代了對象的基礎原型。而不是使用頁面呈現代碼中的通用預編譯對象,它現在必須採取兩件事情:

傳入的變量就是這個。分析它,克隆它。然後將要調用的指定函數注入到新對象中。然後在新對象中執行該功能。之後如果不再叫它清理它。

對象具有較長的綁定時間,因爲引擎需要遍歷所有函數和參數的作用域樹以查看需要複製的內容,因此對象越複雜,範圍越廣。

你已經在使用範圍,我強烈建議。它的內存激化程度較低,引擎不必複製對象,然後調用這些函數。而且您還可以從兩個對象中獲得屬性。

根據我的經驗,綁定從來沒有真正需要。只需使用setter和getters來獲取屬性,否則作用域變量不會總是在主對象中更改。

就拿這個片段

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);