一、 </body>
閉合標籤以前,將全部的<script>
標籤放在頁面底部,確保在腳步執行以前頁面已經完成渲染。javascript
二、 合併腳本。下載單個 100KB 的文件將比下載 4 個 25KB 的文件更快,所以頁面標籤的<script>
標籤越少,加載也就越快,響應也越迅速。不管外鏈文件或者內嵌腳本。html
三、 使用無阻塞下載 javascript
的方法,即在頁面加載完成後才加載 Javascript
代碼,如下有幾種無阻塞下載方法:java
使用<script>
的 defer
屬性(只有 IE4+和 FireFox3.5+支持)node
<script src="file.js" defer></script>
複製代碼
使用動態建立的<script>
元素來下載並執行代碼webpack
// 經過監聽script元素接收完成事件來得到腳本加載完成時的狀態
// 封裝標準和IE特有的實現方法函數
function loadscript(url, callback) {
let script = document.createElement('script');
if (script.readyState) {
//IE
script.onreadystatechange = function() {
if (script.readyState === 'loaded' || script.readyState === 'complete') {
script.onreadystatechange = null;
callback();
}
};
} else {
// 其餘瀏覽器
scripy.onload = function() {
callback();
};
}
script.src = url;
document.getElementsByTagName('head')[0].appendchild(script);
}
// 使用上述封裝函數加載文件
loadscript('file.js', function() {
console.log('file is loaded ~');
});
複製代碼
使用 XHR 對象下載 javascript
代碼並注入頁面中web
let xhr = new XMLHttpRequest();
xhr.open('get', 'file.js', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
let script = document.createElement('script');
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
};
複製代碼
總結:算法
向頁面中添加大量 JavaScript
的推薦作法:先添加動態加載所需代碼,而後加載初始化頁面所需剩下代碼跨域
一、訪問字面量和局部變量的速度比訪問數組元素和對象成員快,所以儘可能使用字面量和局部變量,減小數組項和對象成員的使用。數組
二、儘量使用局部變量。若是某個跨做用域的值在函數中被引用一次以上,把它存儲到局部變量中。瀏覽器
// 不推薦
function initFn() {
// document.getElementById('myImg')屢次被引用
document.getElementById('myImg').src = 'photo.png';
document.getElementById('myImg').alt = 'photo';
}
// 推薦
function initFn() {
// 改寫
let myImg = document.getElementById('myImg');
myImg.src = 'photo.png';
myImg.alt = 'photo';
}
複製代碼
三、避免使用 with 語句,它會改變執行環境做用域鏈。try-catch 中的 catch 也有一樣的影響,看實際狀況中進行運用。
四、屬性和方法在原型鏈中的位置越深,訪問的速度越慢
總結:
把經常使用的對象成員、數組元素、跨域變量保存在局部變量中
一、最小化 DOM 訪問次數,若是須要屢次訪問某個 DOM 節點,使用局部變量存儲它的引用。
// 不推薦
function innerHTMLLoop(){
for(let i = 0; i < 5; i++){
document.getElementById('myDiv').innerHTML += 'a';
}
}
// 推薦
function innerHTMLLoop(){
let content = '';
for(let i = 0; i < 5; i++){
content += 'a';
}
document.getElementById('myDiv').innerHTML = content;
}
複製代碼
二、若是須要在迭代中使用 HTML 集合,把它的長度緩存到一個變量中;若是須要屢次操做集合,把它拷貝到一個數組中。
HTML 集合有document.getElementsByName()
,document.getElementsClassName()
,document.getElementsByTagName()
,document.images
,document.links
,document.forms
等等,返回的是相似數組的列表,可是它以一種「假定實時態」實時存在,即當底層文檔對象更新時,它也會自動更新。
// 死循環
let divs = document.getElementsByTagName('div');
for (let i = 0; i < divs.length; i++) {
document.body.appendChild(document.createElement('div'));
}
複製代碼
當遍歷一個集合時,把集合存儲在局部變量中,並把 length 緩存在循環外部
// 推薦
function collectNodes() {
let coll = document.getElementsByTagName('div');
let len = coll.length;
let nodeName = '';
let tagName = '';
let el = null;
for (let i = 0; i < len; i++) {
el = coll[i];
nodeName = el.nodeName;
tagName = el.tagName;
}
return { nodeName, tagName };
}
複製代碼
三、減小重繪和重排,批量修改樣式時,「離線」操做 DOM
樹,使用緩存,並減小訪問佈局信息的次數。
當頁面佈局和幾何屬性改變時須要「重排」。下列狀況均會發生「重排」:
一、添加或刪除可見的 DOM
元素
二、元素位置發生改變
三、元素尺寸改變(包括:外邊距、內邊距、邊框厚度、寬度、高度等屬性改變)
四、內容改變,如文本改變或圖片被另外一個不一樣尺寸的圖片代替
五、頁面渲染器初始化
六、瀏覽器窗口改變
完成「重排」後,瀏覽器會從新繪製受影響的部分到屏幕中,過程爲「重繪」。
減小「重繪」和「重排」
一、使元素脫離文檔流
二、對其應用屢次改變
三、把元素帶回文檔中
// 第一種方式:隱藏元素,應用修改,從新顯示
let ul = document.getElementById('nyList');
ul.style.display = 'none';
// 向ul中添加附加數據
appendDataToElement(ul, data);
ul.style.display = 'block';
// 第二種方式:使用文檔片斷(document fragment)在當前DOM以外構建一個子樹,再把它拷貝到文檔(推薦)
let fragment = document.createDocumentFragment();
// 向fragment中添加附加數據
appendDataToElement(ul, data);
document.getElementById('myList').appendChild(fragment);
// 第三種方式:將原始元素拷貝到一個脫離文檔的節點中,修改副本,完成後再替換原始元素
let old = document.getElementById('myList');
let clone = old.cloneNode(true);
// 向clone中添加附加數據
appendDataToElement(ul, data);
old.parentNode.replaceChild(clone, old);
複製代碼
四、使用事件委託減小事件處理器的數量
// Event對象提供了一個屬性叫target,能夠返回事件的目標節點,咱們成爲事件源,也就是說,target就能夠表示爲當前的事件操做的dom,可是不是真正操做dom,固然,這個是有兼容性的,標準瀏覽器用ev.target,IE瀏覽器用event.srcElement。
myLi.onclick = function(e) {
let e = e || window.event;
let target = ev.target || ev.srcElement;
if (target.nodeName.toLowerCase() == 'li') {
alert(target.innerHTML);
}
};
複製代碼
// 將返回值集合存入數組
let results = [result0,result1,result2,result3,result4,result5,result6,result7,result8,result9,result10,];
// 返回當前結果
return results[value];
複製代碼
合併 JavaScript 文件以減小 HTTP 請求數
使用 webpack 壓縮 JavaScript 文件
使用 CDN 提供 JavaScript 文件;CDN 不只能夠提高性能,也會爲你管理文件的壓縮和緩存
參考:圖靈圖書《高性能JavaScript》