做用域鏈的查找是逐層向上查找。查找的層次越多,速度越慢。隨着硬件性能的提高和瀏覽器引擎的優化,這個慢咱們基本能夠忽略。html
除了層級查找損耗的問題,變量的修改應只在局部環境進行,儘可能避免在局部環境下去操做修改父級變量的值。(react/vue 單向數據流的數據傳輸方式)前端
優化方法:聲明一個變量存儲引用(該方法應用甚多)vue
// 未優化(window.location.href 3*2 6次) var query = window.location.href.substring(window.location.href.indexOf('?')); // 優化後(3次,之後屢次調用url,查詢次數不會增長) var url = window.location.href; var query = url.substring(url.indexOf('?')); url = null;
函數裏面聲明的變量,在函數調用棧執行後退出時,會自動清除引用。而全局變量和閉包則會與之相反,繼續保存,因此使用用後需手動標記清除,以避免形成內存泄漏。react
平常應用很少,與增值迭代的區別,就在i存儲的值。減值迭代i的值不斷在變小,存儲的空間也在變小。jquery
但在前端極少須要遍歷上萬次上億次的數據,上千上百都不多,因此這個優化可忽略。並且咱們遍歷的順序通常都是從數組頭部開始,因此增值迭代應用的更多。數組
// 增值迭代(用的較多) for(var i = 0; i < len; i++) { //... } // 減值迭代 for(var i = len - 1; i >= 0 ; i--) { //... }
終止條件應該是一個固定值判斷,應避免在終止條件上作其餘運算(屬性查找等)。瀏覽器
// 未優化,每次循環都會去計算數組長度 var arr = ['HTML', 'CSS', 'JavaScript']; for (var i = 0; i < arr.length; i++) { //... } // 優化後 for (var i = 0, len = arr.length; i < len; i++) { //... } // 聲明瞭一個變量len用於儲存數組長度,只會計算一次
循環體的代碼應該着重於只須要遍歷處理的代碼,其餘無關代碼應放置到循環體外面。閉包
最經常使用的for循環和while循環都是前測試循環。而do-while這種後測試循環,能夠避免最初終止條件的計算,所以運行更快。前測試循環(for/while),可能一次都不會執行循環體app
後測試循環(do...while),至少執行一次less
// for循環遍歷 var arr = ['HTML', 'CSS', 'JavaScript']; for (let i = 0, len = arr.length; i < len; i++) { arr[i]; } // 肯定索引值 arr[0]; arr[1]; arr[2];
TIPS: 判斷優化,最可能的到最不可能的順序組織(if/switch
)
符合 write less, do more 的代碼追求
// 多個var聲明 var name = 'KenTsang'; var age = 28; var job = 'Developer'; // 合併一個var聲明 var name = 'KenTsang', age = 27, job = 'Developer';
// 優化前 var name = value[i]; i++; // 優化後 var name = value[i++];
建立引用類型可使用構造函數和字面量兩種方式,不過平常習慣都使用字面量,由於語句更簡潔,寫起來更像數據封裝。
// 字面量 var arr = [1, 2, 3, 4]; var obj = { name: 'KenTsang' } // 構造函數 var arr = new Array(1, 2, 3, 4); var obj = new Object(); obj.name = 'KenTsang';
現場更新:一旦你須要訪問的 DOM 部分是已經顯示的頁面的一部分,那麼你就是在進行一個現場更新
文檔片斷至關一個臨時的佔位符,只有片斷中的內容會被添加到DOM上,片斷自己並不會被添加。
// 代碼片斷標籤 var ele = document.getElementById('ul'); var fragment = document.createDocumentFragment(); var browsers = ['Firefox', 'Chrome', 'Opera', 'Safari', 'IE']; browsers.forEach(function(browser) { var li = document.createElement('li'); li.textContent = browser; fragment.appendChild(li); }); // 只會操做一次DOM ele.appendChild(fragment);
合併插入代碼一次性設置innerHTML。
// 優化前:操做屢次DOM var list = document.getElementById("myList"); for (var i=0; i < 10; i++) { list.innerHTML += "<li>Item " + i + "</li>"; } // 優化後:操做一次DOM var innerHtml = ''; for (var i = 0; i < 10; i++) { innerHtml += '<li>Item' + i + '</li>'; } list.innerHTML = innerHtml;
經過事件流——冒泡機制實現代理,子元素事件觸發冒泡到父元素,由父元素綁定一個事件進行統一處理,避免多個事件綁定影響性能。
<ul class="list"> <li class="item">HTML</li> <li class="item">CSS</li> <li class="item">JavaScript</li> </ul> var listEle = document.getElementById('list'); listEle.addEventListener('click', function(event) { if (event.target.className.indexOf('item') > -1) { console.log(event.target.innerHTML); } }) // jquery $('#list').on('click', '.item', function(event){ console.log($(this).html()); })
任什麼時候候要訪問 HTMLCollection,無論它是一個屬性仍是一個方法,都是在文檔上進行一個查詢,這個查詢開銷很昂貴。
// 一個死循環例子 <a href="">link</a> var existLinkEle = document.getElementsByTagName('a'); for (var i = 0; i < existLinkEle.length; i++) { console.log(i); var linkEle = document.createElement('a'); document.body.appendChild(linkEle); } // body會不斷地插入a標籤
由於existLinkEle.length
每次循環都會從新計算頁面a節點的數量,而獲得的值一直遞增。
// 優化(一個變量存儲引用) var len = existLinkEle.length; for (var i = 0; i < len; i++) { //... }
返回HTMLCollection
對象狀況有:
document.getElementByTagName()
。childNodes
屬性attributes
屬性document.forms
,document.images
等參考文檔
做者:以樂之名 本文原創,有不當的地方歡迎指出。轉載請指明出處。