最近在讀《高性能javascript》,在這裏記錄一下讀後的一些感受,順便加上自己的一些理解,如果有興趣的話可以關注的我的博客http://www.bloggeng.com/,我會不定期發佈一些前端教程還有前端乾貨,話不多說,進入我們的正題
一、js優化之加載
1、script標籤放在底部,不要放在head標籤;
2、儘量減少js文件數量
3、給script標籤添加一個defer屬性,defer屬性指明所含的腳本不會修改DOM,因此代碼能安全地延遲執行。
<script type="text/javascript" src="file.js" defer></script>
4、把loadScript()函數直接嵌入頁面,從而 避免多產生一次HTTP請求;一旦頁面初始化所需要的代碼完成下載,你可以繼續自由地使用loadScript();去加載頁面其他的功能所需要的腳本;
5、YUI3的方式、LazyLoad類庫(自己百度一下這個腳本)
6、LABjs:(這個也是一個腳本文件,可以自己搜索一下哈)
$LAB.script()方法用來定義需要下載的js文件,$LAB.wait()用來指定文件下載並執行完畢後所調用的函數
二、數據存取優化
1、函數中讀寫局部變量總是最快的,讀寫全局變量通常是最慢的。請記住,全局變量總是存在於執行環境作用域鏈的最尾端,因此他也是最遠的。對所有瀏覽器而言,總分趨勢是,一個標識符所在的位置越深,它的讀寫速度也就越慢。
最好的方式是把使用一次以上的全局變量用局部變量代替。例如:
Var doc =document;
2、對象成員--原型
js中的對象是基於原型的。原型是其他對象的急促,它定義並實現了一個新創建的對象所必須包含的成員列表。
因此對象可以有兩種類型:實例成員和原型成員。實例成員直接存在於對象實例中,原型成員則從對象原型繼承而來。
3、對象成員--原型鏈
使用構造函數Book來創建一個新的Book實例。實例boo1的原型(_proto_)是Book.prototype,而Book.prototype的原型是object。
4、避免使用with語句,因爲他會改變執行環境作用域鏈。同樣,try-cath語句中catch子句也有同樣的影響,因此也要小心使用;
5、通常來說,可以通過吧常用的對象成員、數組元素、跨域變量保存在局部變量中來改善js性能,因爲局部變量訪問速度更快。
三、優化DOM編程
1、var element= document.querySelectorAll("#menu a ");
最新的瀏覽器提供了一個名爲querySelectorAll()的原聲dom方法;
2、獲取頁面中有些class爲‘waring’和‘notice’的元素
Var errs = document.querySelectorAll('div.waring,div.notice');
3、爲了防止頁面多次重排,可以將樣式的修改合併在一起然後一次處理,這樣只會修改一次DOM
Var el = document.getElementById('mydiv');
el.style.cssText ="border:1px solid red;border-right:2px;padding:5px;"
這樣會覆蓋已存在的樣式信息,如果保留現有樣式,可以:
el.style.cssText +=‘;border-left:1px;’;
另外一種就是修改class的名稱;
4、一個減少重排的方式是通過改變display睡醒,臨時從文檔中移除元素,然後再恢復他
5、另外一種減少重排的方法是在文檔之外創建並更新一個文檔片段,然後把它附加到原始列表中。
Var fragement = document.getElementById(“mylist”);
appendDataToElement(fragement,data);
Document.getElementById('mylist').appendChild(fragement);
6、還有一種解決方案是爲需要修改的節點創建一個備份,然後對副本進行操作,一旦操作完成,就用新的節點替代舊的節點
Var old = document.getElementById(“mylist”);
Var clone = old.cloneNode(true);
appendDataToElement(clone,data);
Old.parentNode.replaceChild(clone,old);
推薦使用文檔片段的方案,因爲所產生的DOM遍歷和重拍次數最少。
(持續更新。。。。華麗的分割線)
2017年9月19日
7、使用絕對定位定位頁面上的動畫元素,將其脫離文檔流
8、避免大量的元素使用:hover僞類,會降低響應速度
四、算法與流程控制
(一)、循環
1、循環與循環的類型
(1)標準for循環:在for循環中定義的變量相當於在循環體外定義一個新變量,因爲javascript只有函數級作用域;
(2)while循環:前測循環,由一個前測條件和一個循環體構成,在循環體執行以前,先計算前測條件;
(3)do-while循環:後測循環,循環體至少運行一次,然後再由後測條件決定是否再次運行;
(4)for-in循環:可以枚舉任何對象的屬性名
for(var prop in object){//循環體}
循環體每次運行時,prop變量被賦值爲object的一個屬性名,直到所有的屬性遍歷完成才返回。包含了實例屬性和原型鏈中集成的屬性
2、循環性能
(1)for-in循環比其他幾種明顯要慢,儘量不要使用for-in遍歷數組成員
(2)每次循環都要查找items.length,這樣很耗時,由於此值在循環過程中不會改變,因此產生了不必要的性能損失。爲了提高這個循環的性能,只查找一次屬性,把items.length的值存儲到一個局部變量,然後再控制條件裏使用這個變量;(再大多數瀏覽器中能節省25%的運行時間)
(3)還可以通過顛倒數組的順序來提高循環性能,通常,數組的順序與所要執行的任務無關,因此從最後一項開始向前處理是一個備選方案。
// 減少屬性查找並反轉 for(var i=items.length;i--;){ process(items[i]); } Var j =items.length; While(j--){ process(items[i]); }
這裏使用了倒序循環,並把減法操作在控制條件中。現在每個條件只是簡單地與0比較。控制條件與true比較是,任何非零數會自動轉換爲true,而零值等同於false。實際上,控制條件已經從兩次比較(迭代數少於總數麼?他是否爲true?)減少到一次比較(它是true麼?)。每次迭代從兩次比較減少到一次,進一步提高了循環速度。通過倒敘循環和減少屬性查找,可以看到運行速度比原始版本快了50%~60%;
對比原始版本,每次迭代只有如下的操作: