隨着計算機硬件的不斷升級,開發者愈加以爲Javascript
性能優化的好很差對網頁的執行效率影響不明顯,因此一些性能方面的知識被不少開發者忽視。但在某些狀況下,不優化的Javascript
代碼必然會影響用戶的體驗。所以,即便在當前硬件性能已經大大提高的時代,在編寫Javascript
代碼時,若能遵循Javascript
規範和注意一些性能方面的知識,對於提高代碼的可維護性和優化性能將大有好處。那麼,接下來咱們討論幾種可以提升JavaScript性能
的方法。javascript
<script>
標籤放到
<body>
標籤的底部
js
文件,減小頁面中
<script>
標籤改善性能
defer
屬性,加載後續文檔元素的過程將和
script.js
的加載並行進行,可是
script.js
的執行要在全部元素解析完成以後,
DOMContentLoaded
事件觸發以前完成。
async
屬性,加載和渲染後續文檔元素的過程將和
script.js
的加載與執行並行進行
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'file.js';
document.getElementsByTagName('head')[0].appendChild(script);複製代碼
標識符所在的做用域鏈的位置越深,那麼它的標識符解析的性能就越慢。因此一個好的性能提高的經驗法則是:若是某個跨做用域的值在函數中被引用一次以上,那麼就把它存儲到局部變量裏。css
function fun1() {
// 將全局變量的引用先存儲在一個局部變量中,而後使用這個局部變量代替全局變量,從而提升
// 性能;否則每次(3次)都要遍歷整個做用域鏈找到
document var doc = document;
var bd = doc.body;
var links = doc.getElementsByTagName('a');
doc.getElementById('btn').onclick = function(){
console.log('btn');
}
}複製代碼
方法或屬性在原型鏈中存在的位置越深,搜索它的性能也就越慢,因此要避免N多層原型鏈的寫法。java
對象的嵌套成員,對象成員嵌套越深,讀取速度也就越慢。因此好的經驗法則是:若是在函數中須要屢次讀取一個對象屬性,最佳作法是將該屬性值保存在局部變量中,避免屢次查找帶來的性能開銷。編程
function f() {
// 由於在如下函數中須要3次用到DOM對象屬性,因此先將它存儲在一個局部變量
// 中,而後使用這個局部變量代替它進行後續操做,從而提升性能
var dom = YaHOO.util.Dom;
if(Dom.hasClass(element,'selected')){
Dom.removeClass(elemet,'selected');
}else{
Dom.addClass(elemet,'selected');
}
}複製代碼
用js
訪問和操做DOM
都會帶來性能損失,可經過如下幾點來減小性能損失:數組
DOM
訪問次數;
DOM
節點,請使用局部變量存儲它的引用;
HTML
集合,由於它實時連繫着底層文檔;咱們能夠把集合的長度緩存到一個變量中,並在迭代中使用它;
DOM
元素;offsetTop,offsetLeft,offsetWidthoffsetHeight,
scrollTop,scrollLeft,scrollWidth,scrollHeight,clientTop,clientLeft,clientWidth,clientHeight,getComputedStyle()
等;function f() {
// 推薦使用如下操做
var el1 = document.getElementById('mydiv');
el1.style.cssText = 'border:1px;padding:2px;margin:3px';
// 不推薦使用如下操做
var el2 = document.getElementById('mydiv');
el2.style.border = '1px';
el2.style.padding = '2px';
el2.style.margin = '3px';
}複製代碼
DOM
時,能夠經過如下步驟減小重繪和重排的次數:DOM
元素綁定事件以及瀏覽器須要跟蹤每一個事件處理器都須要消耗性能。str += 'one'+'two';
str= str+'one'+'two';複製代碼
建立對象和數組推薦使用字面量,由於這不只是性能最優也有助於節省代碼量。瀏覽器
var obj = {
name:'tom',
age:15,
sex:'男'
}複製代碼
若是須要遍歷數組,應該先緩存數組長度,將數組長度放入局部變量中,避免屢次查詢數組長度。緩存
JS
提供了三種循環:for(;;)、while()、for(in)
。在這三種循環中 for(in)
的效率最差,由於它須要查詢Hash鍵,所以應儘可能少用for(in)
循環,for(;;)、while()
循環的性能基本持平。性能優化
儘可能少使用eval
,每次使用eval
須要消耗大量時間,這時候使用JS
所支持的閉包能夠實現函數模板。bash
當須要將數字轉換成字符時,採用以下方式:"" + 1
。從性能上來看,將數字轉換成字符時,有以下公式:("" +) > String() > .toString() > new String()
。String()
屬於內部函數,因此速度很快。而.toString()
要查詢原型中的函數,因此速度遜色一些,new String()
須要從新建立一個字符串對象,速度最慢。閉包
當須要將浮點數轉換成整型時,應該使用Math.floor()
或者Math.round()
。而不是使用parseInt()
,該方法用於將字符串轉換成數字。並且Math
是內部對象,因此Math.floor()
其實並無多少查詢方法和調用時間,速度是最快的。