提出問題
如果識別出頁面中JavaScript函數的性能問題,在不同瀏覽器下有不同的測試工具:
-
Firefox下使用Firebug的Profile工具
-
Chrome下使用內置的Profile工具
-
IE9下也有Profile工具
雖然大家的功能一個比一個炫,但是始終解決不了兩個問題:
- 如何只檢測指定命名空間下的函數性能,否則會產生大堆的無用數據。
- 不能跨瀏覽器使用,沒有統一的參照物。同時不同工具之間還有一定差異的背景噪音影響。
還有一點就是仍然佔據主流的IE7和IE8沒有內置的JavaScript性能檢測工具。
尋求解決方案
首先在網上找到的一篇文章是John Resig在2008年6月發表的一篇文章,是夠古老的了,不過還是非常有借鑑意義,它的輸入結果如下所示:
我們來看一下它的核心代碼,這段代碼用來處理jQuery.fn下的所有函數:
for (var method in jQuery.fn)(function (method) {
if (method == "init") return;
var old = jQuery.fn[method];
jQuery.fn[method] = function () {
if (!internal && curEvent) {
internal = true;
var m = curEvent.methods[curEvent.methods.length] = {
name: method,
inLength: this.length,
args: formatArgs(arguments)
};
var start = (new Date).getTime();
var ret = old.apply(this, arguments);
m.duration = (new Date).getTime() - start;
if (curEvent.event == "inline") curEvent.duration += m.duration;
if (ret && ret.jquery) m.outLength = ret.length;
internal = false;
return ret;
} else {
return old.apply(this, arguments);
}
};
})(method);
從這段代碼中,我們看到如下一些步驟:
- 將需要處理的函數備份起來:var old = jQuery.fn[method];
- 使用一個新的函數覆蓋此函數:jQuery.fn[method] = function () {
-
在新函數內,調用備份的原始函數,並在調用前後添加計時代碼,以確定本次調用這個原始函數的時間:
var start = (new Date).getTime(); var ret = old.apply(this, arguments); m.duration = (new Date).getTime() - start;
有了這個核心概念,我們可以寫個自己的JavaScript的Profile功能,而不僅僅是侷限於檢測jQuery代碼,我們要讓用戶自己指定要檢測的JavaScript命名空間!
我的開源實現
我的開源實現:http://code.google.com/p/jprofile/
它的最大特點:
- 可以指定測試的命名空間
- 可以跨瀏覽器使用
使用起來非常方便,只需要如下幾個步驟:
-
在頁面的最後引入jprofile.js。(這也是安裝jprofile開源解決方案的全部步驟!)
-
打開頁面,可以看到右上角的那個Enable jProfile按鈕:
-
點擊那個按鈕,會彈出一個對話框,輸入你要檢測的命名空間,比如"jQuery":
-
點擊確定,頁面會自動刷新,並顯示jProfile工具條。點擊Display按鈕顯示結果:
跨瀏覽器測試jQueryUI
下面就讓我們使用jProfile測試一下jQueryUI首頁JavaScript的性能,以下是測試數據。 你可以自己試一下,在線示例地址。
-
Firefox
-
IE7
-
IE8
這是個跨瀏覽器JavaScript性能檢測的奇蹟,至於你信不信,我反正信了。