JavaScript是一種非常靈活的語言,我們可以隨心所欲地編寫各種類型的代碼,不同類型的代碼執行效率的也是不一樣的,不過在開發過程中,有許多方法可以分散地提高代碼性能,那么JS提交效率的經驗訪談大家都了解嗎?一起跟著錯新技術頻道小編的步伐來了解一下吧!
首先,要謝謝CSDN hbhbhbhbhb1021(天外水火(我要多努力))和cuixiping(無心)的提醒。我會抽空把IE專有的方法如:insertAdjacentHTML的速度也給測出來看看是否合適大量數據時IE下,不用innerHTML的速度。
這里的主要測試不是指生成數據時的速度,指的是匹配速度 ,例如
我這里的匹配速度
我測的10000條數據,有效數據為1000-1100條,輸出復雜的HTML,速度為360ms左右,方法為 正則匹配Match(有循環)
希望貼出您的測試數據。
行innerHTML和insertAdjacentHTML速度的測試,比均結果相差不會大于20ms(平均速度),在IE中insertAdjacentHTML速度還是很快的,在Mozilla下是得不償失的。
可以點擊這里進行簡單的匹配測試
點擊這里進行innerHTML和insertAdjacentHTML速度的測試,可以兼容Mozilla的
寫這篇文章,其間我也是刪刪減減的,所以語句也不怎么通順,看的朋友也就辛苦了一些了。
本文主要是出于有朋友使用我原來寫的autocomplete的JS控件。當數據量大的時候,會出現效率極其慢的情況,我在這段時間做出的一些測試也及一些經驗,與大家分享,如果有錯的地方,還請指出。
經過測試,我們會發現如下的情況或者說的結論,如果您的測試結果與我的不符,請說明原因,以便相互學習。
1)當一個較大的HTML字符串給到obj.innerHTML時會出現麻煩。也就是說當一個較大的字符串在賦予一個Element的innerHTML時,這個過程將可能是我們無法容忍的。(而事實上這并非JS的錯,而確實是String數據量太多)
2)用拼合字符串的方法可以使效率提高,在字符串較大時,2)的情況仍然出現。超過一定的數量,速度會明顯慢下來。
3)正則匹配的方法會比平常遍歷的方法要高效一些。
4)在執行過程中,綁定事件的時間會花費更多一些。測試在1w條數據情況下,大約是匹配以及生成HTML數據的30倍,也就是說生成數據總花費100ms,而綁定事件則需要3000ms。
5)總體來說。IE的速度要比Mozilla要慢(我用的是Firefox1.5做的測試)。
6)大數據量時,不要用DOM生成Element。
7)非JS內置方法,也許會引發很多時間過多重復的勞動而且可能事得其反。建議盡可能利會內置方法。
總結問題:
一、在把字符串給到innerHTML上。
二、循環綁定事件所花費時間。
三、生成我們需要的DIV所花時間。
四、不同的瀏覽器問題。
下面對癥下藥:
問題一
我們可以做的沒有其它的,只有盡可能少的HTML字符串,比如最基本的一個DIV,可以這樣寫
也可以這樣寫
,第二種就比第一種速度明顯要快的。如果還不行的話,請看下面這個方法對你是否合適
在做程序的時候突然想起來51js上PK tree,一位版主所寫的一棵樹,1百萬的一個節點,動態載入。只需要不到1秒。毫無疑問,肯定是取巧了,因為只要只生tree的html就是一個很大的數量。這個樹的特別的地方就是生成樹時,并非把1百萬的節點都一次生成innerHTML,而是只生成在視角范圍內的節點,當滾動條向下滾的時候,才動態的再生成樹節點。這個方法至少我覺得思想很開闊,很有價值。
我們所知道,mySQL數據庫里取數據可以這么取。SELECT * FROM table limit 0,100,意思是只取數據庫中的0-100條數據。說到這里可能有些朋友也想到了,在JS中,我們可以利用這個方法來取數據,將一個數組看作是一個表。只是單純的數據表,非二維表。如圖

利用這一些,我們可以把數據有效的值先取出來。如圖:

想想看。假如我們取一個數組,下標為10000,設生成一個autocomplete的節點HTML長度20(已經非常小了"
)。
匹配數據已知:有3000條數據
輸節字節數為:3000(asc碼)也就是3000*20=60000字節
而用limit方法,輸出為:10*20=200字節。
很明顯的差距!
之后我們便可以分步求解,即當滾動條出現,或者按下down(方向鍵)再動態的生成innerHTML。
8-13更新:測了一下,用自己寫的limit的速度,和自帶的Array.slice的速度比了一下,速度差不多,而且有的時候還比slice的速度還要快一些。
Array.prototype.limit = function(l, h) {
var _a = this; var ret = [];
l = l<0?0:l; h = h>_a.length?_a.length:h;
for (var i=0; i<_a.length; i++) {
if (i>=l && i<=h) ret[ret.length] = _a[i];
if (i>h) break;
}; return ret;
}
有興趣的朋友也可以自己測一下,貼出數據,看看哪個效率更好。
問題二、
為什么我們還要循環來綁定事件呢?
還是由于問題一。
假設這樣寫
1)
還可以這樣寫
2)
document.getElementById("container").childNodes[0].onclick=function(){handlerClick()};
這樣也可以省掉一些字符串,從而節省字符串資源。但又需要把container的子元素再遍歷,所以也會花費時間,用第一種方法還是第二種?我建議還是用第一種,但最好把字符串減到最低,如:
大數據量情況下,還是越少字符越好,雖然代碼不怎么美觀。
問題三、
生成DIV時我們可以這樣生成
var div = document.createElement("DIV");
div.onclick=function(){};
//TODO
也可以這樣用字符串
var sHtml = "
";
當數量小時,第一種速度會比第二種快。但當達到一個數量級時,第二種要明顯比第一種快。總體來說第二種較好。因為第二種還可以更靈活,比如利用join,還有正則匹配。
問題四、
這個問題也不容忽視的。每個browser有不同的特點,速度執行也有不同,我個人覺得,這點和JS上優化效率上是一樣的。
盡可能的利用瀏覽器本身的內置方法,這樣大多數情況下也可以把效率提高。
那么如何能夠把腳本的效率提高起來呢?
1)用match匹配,一個aCache數組。循環match.length,并給aCache,之后用join(""),再給到innerHTML(此方法仍然需要循環,而且需額外的一個數組做臨時數據存儲)
2)無需循環,但必須在生成數據時也額外生成指定字符串。(此方法也需要額外的空間做臨時數據)如圖:

3)寧可多次判斷,也不重復進行一次重新匹配。e.g:
input控件中第一次取到的值為:1,第二次按下的值為12
如果進行判斷的話,可以事件存儲一個值,也就是前一次按下的值。如上面的值1。第二次按下時沒有退格,即再在前面的值中加一個字符2,那么我們將在前面1中匹配出的數據中進行匹配。這樣可以大大的減輕循環的次數。
4)利用問題一中所寫的limit,將數據動態取出。這些能夠很好的解決HTML字符串過大的問題,但此方法控制不當的話,也會事得其反。
5) 利用range技巧來加入HTMLStr,也就是說,當一個HTML字符串太大時,再用innerHTML+=anotherHTMLStr,這樣的方法,也是會讓速度太慢,在IE中,我們可以用obj.insertAdjacentHTML("beforeEnd", anotherHTMLStr)這樣的方法來插入HTML,這個方法經過測試,比較穩定。利用limit再加上insertAdjacentHTML,會使得插入的HTML代碼速度更穩定,而在Mozilla中,則要利用range的技巧來達到此目的,如下:
后記:效率問題沒有一個完整的解決方法,只有實踐中根據需要而定。因此,上面的方法僅供您參考,如果你也有一些好的方法,可以在評論中寫下您的經驗,以便交流。
上文是錯新技術頻道小編為大家搜集到的相關介紹,希望對你了解JS提高效率的經驗訪談有所幫助!
新聞熱點
疑難解答
圖片精選