本文講述了JavaScript提升性能的常用技巧。分享給大家供大家參考,具體如下:
1.注意作用域
隨著作用域鏈中的作用域數量的增加,訪問當前作用域以外的變量的時間也在增加.訪問全局變量總是要比訪問局部變量慢,因為要遍歷作用域鏈.
1). 避免全局查找 將在一個函數中會多次用到的全局對象存儲為局部變量總是沒錯的.
2). 避免 with 語句 with會創建自己的作用域,因此會增加其中執行代碼的作用域鏈的長度.
2.選擇正確的方法
性能問題的一部分是和用於解決問題的算法或者方法有關的.
1). 避免不必要的屬性查找
在計算機科學中,算法的復雜度是使用O符號來表示的.最簡單,最快捷的算法是常數值,即O(1).之後,算法變得越來越復雜並花更長時間執行.常用的JavaScript算法類型有:
常數 : 不管有多少值,執行的時間都是恆定的.一般表示簡單值和存儲在變量的值.
對數 : 總的執行時間和值的數量相關,但是要完成算法並不一定要獲取每個值. 例如:二分查找
線性 : 總執行時間和值的數量直接相關. 例如 :遍歷某個數組中的所有元素
平方 : 總執行時間和值的數量有關,每個值至少要獲取n次.例如:插入排序
立方: 總執行時間和值的數量有關,每個值至少要獲取n的平方次
使用變量和數組要比訪問對象上的屬性更有效率.對象上的任何屬性的查找都要比訪問變量或者數組花更長時間,因為必須在原型鏈中對擁有該名稱的屬性進行一次搜索.
一般來講,只要能減少算法的復雜度,就要盡可能減少.盡可能多地使用局部變量將屬性查找替換為值查找.進一步講,如果即可以用數字化的數組位置進行訪問,也可以使用命名屬性(諸如NodeList對象),那麼使用數組位置.
2). 優化循環
a. 減值迭代 在很多情況下,從最大值開始,在循環中不斷減值的迭代器更加高效.
b. 簡化終止條件 由於每次循環過程都會計算終止條件,所以必須保證它盡可能快.
c. 簡化循環體 循環體是執行最多的,所以要確保其被最大限度地優化.確保沒有某些可以被很容易移出循環的密集計算.
d. 使用後測試循環 最常用的for循環和while循環都是前測試循環.而如do-while這種後測試循環,可以避免最初終止條件的計算,因此更快.
3). 展開循環 當循環的次數是確定的,消除循環並使用多次函數調用往往更快.如著名的Duff裝置
4). 避免雙重解釋
當JavaScript 代碼想解析 JavaScript 的時候就會存在雙重解釋的懲罰.如下例:
eval("alert('Hello world!')"); //某些代碼求值
修正:
alert('Hello world');
var sayHi = new Function("alert('Hello world!')");
修正:
var sayHi = function(){ alert("Hellow world!'); };
setTimeout("alert('Hellow world!')",500);
修正:
setTimeout(function)({ alert('Hellow world!'); },500);
5). 其他方法
原生方法較快--只要有可能,使用原生方法而不是自己用JavaScript重寫一個.原生方法是用諸如C/C++之類的編譯型語言寫出來的,所以要比JavaScript的快很多很多.JavaScript中最容易被忘記的就是可以在Math對象中找到的復雜的數學運算;這些方法要比任何用JavaScript寫的同樣方法,如正弦,余弦快的多.
Switch 語句較快--如果有一系復雜的if-else語句,可以轉換成單個switch語句則可以得到更快的代碼.還可以通過將case語句按最可能的到最不可能在順序進行組織,來進一步優化switch語句.
位運算符較快--當進行數學運算的時候,位運算操作要比任何布爾運算或者算數運算快.選擇性的用位運算換算數運算可以極大提升復雜計算的性能.諸如取模,邏輯與和邏輯或都可以考慮用位運算來替換.
3 . 最小化語句數
1). 多個變量聲明
如:
//4個語句---很浪費 var count = 5; var color = "blue"; var values = [1,2,3]; var now = new Date();
優化:
var count = 5, color = "blue", values = [1,2,3], noiw = new Date();
在大多數情況下這種優化都非常容易做,並且要比單個變量分別聲明快很多.
2). 插入迭代值
如:
var name = values[i]; i++;
優化:
var name = values[i++];
3). 使用數組和對象字面量
如:
var values = new Array(); ---> var values = [];
var obj = new Object(); ---> var obj = {};
4. 優化DOM交互
1). 最小化現場更新
一旦你需要訪問DOM部分是已經顯示的頁面的一部分,那麼你就是在進行一個現場更新.之所以叫現場更新,是因為需要立即(現場)對頁面對用戶的顯示進行更新.不管是插入單個字符,還是移除整個片段,都有一個性能懲罰,因為浏覽器要重新計算無數尺寸以進行更新.
例:
var list = document.getElementById("myList"); for(var i = 0;i < 10;i++){ var item = document.createElement("li"); list.appendChild(item); item.appendChild(document.createTextNode("Item "+i)); }
這樣添加10個項目,這個操作總共要完成20個現場更新. 下面用創建文檔碎片的方法改進:
var list = document.getElementById("myList"); var fragment = document.createDocumentFragment(); for(var i = 0; i < 10;i++){ fragment.appendChild(item); item.appendChild(document.createTextNode("Item "+i)); } list.appendChlid(fragment);
在這個例子中只有一次現場更新,它發生在所有項目都創建好之後.文檔碎片用作一個臨時的占位符,放置新創建的項目.然後使用appendChild()將所有項目添加到列表用.記住,當給appendChild()傳入文檔碎片時,只有碎片中的子節點被添加到目標,碎片本身不會被添加的.
一旦需要更新DOM,請考慮使用文檔碎片來構建DOM結構,然後將其添加到現存的文檔中.
2). 使用innerHTML
有兩種在頁面上創建DOM節點的方法:使用諸如createElement(),appendChild()之類的DOM方法,以及使用innerHTML對於小的DOM更改而言,兩種方法效率都差不多.而對於大的DOM更改,使用innerHTML要比使用標准DOM方法創建同樣的DOM結構快很多.同樣,一次使用innerHTML比多次使用innerHTML也要快相當多.
3). 使用事件代理(簡,略)
4). 注意NodeList
最小化訪問NodeList的次數可以極大的改進腳本的性能.
發生以下情況時會返回NodeList對象:
a. 進行了對getElementsByTagName()的調用
b. 獲取了元素的childNodes屬性
c. 獲取了元素的attributes屬性
d. 訪問了特殊的集合,如document.forms , document.images等等
要了解當使用NodeList對象時,合理使用會極大提升代碼執行速度.
前面介紹的 函數節流 也是很重要的一方面。特別是多重循環,非常耗性能時,此方法很有用的。
PS:對於javascript進行壓縮,減少代碼體積也是提升javascript性能的有效途徑。這裡就為大家推薦2款非常實用的壓縮工具:
JavaScript壓縮/格式化/加密工具:
http://tools.jb51.net/code/jscompress
jsmin在線js壓縮工具:
http://tools.jb51.net/code/jsmincompress
更多關於JavaScript相關內容感興趣的讀者可查看本站專題:《JavaScript切換特效與技巧總結》、《JavaScript查找算法技巧總結》、《JavaScript動畫特效與技巧匯總》、《JavaScript錯誤與調試技巧總結》、《JavaScript數據結構與算法技巧總結》、《JavaScript遍歷算法與技巧總結》及《JavaScript數學運算用法總結》
希望本文所述對大家JavaScript程序設計有所幫助。