28.2 性能
28.2.1 作用域意識
第 4 章討論過 JavaScript 作用域的概念,以及作用域鏈的作業原理,隨著作用域鏈中作用域數量的
增加,訪問當前作用域外部變數所需的時間也會增加,訪問全域變數始終比訪問區域變數慢,因為必須
遍歷作用域鏈,任何可以縮短遍歷作用域鏈時間的舉措都能提升代碼性能,
- 避免全域查找
改進代碼性能非常重要的一件事,可能就是要提防全域查詢,全域變數和函式相比于區域值始終是
最費時間的,因為需要經歷作用域鏈查找,來看下面的函式:
function updateUI() {
let imgs = document.getElementsByTagName(“img”);
for (let i = 0, len = imgs.length; i < len; i++) {
imgs[i].title = ‘${document.title} image KaTeX parse error: Expected 'EOF', got '}' at position 8: {i}'; }? let msg = doc…{doc.title} image ${i}’;
}
let msg = doc.getElementById(“msg”);
msg.innerHTML = “Update complete.”;
}
這里先把 document 物件保存在區域變數 doc 中,然后用 doc 替代了代碼中所有的 document,
這樣呼叫這個函式只會查找一次作用域鏈,相對上一個版本,肯定會快很多,
因此,一個經驗規則就是,只要函式中有參考超過兩次的全域物件,就應該把這個物件保存為一個
區域變數,
28.2.2 選擇正確的方法
與其他語言一樣,影響性能的因素通常涉及演算法或解決問題的方法,經驗豐富的開發者知道用什么
方法性能更佳,通常很多能在其他編程語言中提升性能的技術和方法同樣也適用于 JavaScript,
- 避免不必要的屬性查找
在計算機科學中,演算法復雜度使用大 O 表示法來表示,最簡單同時也最快的演算法可以表示為常量值
或 O(1),然后,稍微復雜一些的演算法同時執行時間也更長一些,下表列出了 JavaScript 中常見演算法的型別,
常量值或 O(1),指字面量和保存在變數中的值,表示讀取常量值所需的時間不會因值的多少而變化,
讀取常量值是效率極高的操作,因此非常快,來看下面的例子:
let value = 5;
let sum = 10 + value;
console.log(sum);
以上代碼查詢了 4 次常量值:數值 5、變數 value、數值 10 和變數 sum,整體代碼的復雜度可以認
為是 O(1), 在 JavaScript 中訪問陣列元素也是 O(1)操作,與簡單的變數查找一樣,因此,下面的代碼與前面的
例子效率一樣:
let values = [5, 10];
let sum = values[0] + values[1];
console.log(sum);
使用變數和陣列相比訪問物件屬性效率更高,訪問物件屬性的演算法復雜度是 O(n),訪問物件的每個
屬性都比訪問變數或陣列花費的時間長,因為查找屬性名要搜索原型鏈,簡單來說,查找的屬性越多,
執行時間就越長,來看下面的例子:
let values = { first: 5, second: 10 };
let sum = values.first + values.second;
console.log(sum);
這個例子使用兩次屬性查找來計算 sum 的值,一兩次屬性查找可能不會有明顯的性能問題,但幾百
上千次則絕對會拖慢執行速度,
特別要注意避免通過多次查找獲取一個值,例如,看下面的例子:
let query = window.location.href.substring(window.location.href.indexOf("?"));
這里有 6 次屬性查找:3 次是為查找 window.location.href.substring(),3 次是為查找
window.location.href.indexOf(),通過數代碼中出現的點號數量,就可以知道有幾次屬性查找,
以上代碼效率特別低,這是因為使用了兩次 window.location.href,即同樣的查找執行了兩遍,
只要使用某個 object 屬性超過一次,就應該將其保存在區域變數中,第一次仍然要用 O(n)的復雜
度去訪問這個屬性,但后續每次訪問就都是 O(1),這樣就是質的提升了,例如,前面的代碼可以重寫為
如下:
let url = window.location.href;
let query = url.substring(url.indexOf("?"));
這個版本的代碼只有 4 次屬性查找,比之前節省了約 33%,在大型腳本中如果能這樣優化,可能就
會明顯改進性能,
通常,只要能夠降低演算法復雜度,就應該盡量通過在區域變數中保存值來替代屬性查找,另外,如
果實作某個需求既可以使用陣列的數值索引,又可以使用命名屬性(比如 NodeList 物件),那就都應
該使用數值索引,
28.2.4 優化 DOM 互動
在所有 JavaScript 代碼中,涉及 DOM 的部分無疑是非常慢的,DOM 操作和互動需要占用大量時間,
因為經常需要重新渲染整個或部分頁面,此外,看起來簡單的操作也可能花費很長時間,因為 DOM 中
攜帶著大量資訊,理解如何優化 DOM 互動可以極大地提升腳本的執行速度,
- 實時更新最小化
訪問 DOM 時,只要訪問的部分是顯示頁面的一部分,就是在執行實時更新操作,之所以稱其為實
時更新,是因為涉及立即(實時)更新頁面的顯示,讓用戶看到,每次這樣的更新,無論是插入一個字
符還是洗掉頁面上的一節內容,都會導致性能損失,這是因為瀏覽器需要為此重新計算數千項指標,之
后才能執行更新,實時更新的次數越多,執行代碼所需的時間也越長,反之,實時更新的次數越少,代
碼執行就越快,來看下面的例子
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/260600.html
標籤:其他
上一篇:網站原始碼沒有問題,但是抓取診斷,網站標題非法更改了!
下一篇:垂直居中(總結)
