2020-5-6 前端達人
1. 加載和執(zhí)行
盡量將所有的<script>標簽放在</body>標簽之前,確保腳本執(zhí)行前頁面已經(jīng)完成了渲染,避免腳本的下載阻塞其他資源(例如圖片)的下載。
合并腳本,減少頁面中的<script>標簽
使用<script>標簽的defer和async屬性(兩者的區(qū)別見這里)
通過Javascript動態(tài)創(chuàng)建<script>標簽插入文檔來下載,其不會影響頁面其他進程
2.數(shù)據(jù)存取
由于作用域鏈的機制,訪問局部變量比訪問跨作用域變量更快,因此在函數(shù)中若要多次訪問跨作用域變量,則可以用局部變量保存。
避免使用with語句,其會延長作用域鏈
嵌套的對象成員會導致引擎搜索所有對象成員,避免使用嵌套,例如window.location.href
對象的屬性和方法在原型鏈的位置越深,訪問的速度也越慢
3.Dom編程
進行大段HTML更新時,推薦使用innerHTML,而不是DOM方法
HTML集合是一個與文檔中元素綁定的類數(shù)組對象,其長度隨著文檔中元素的增減而動態(tài)變化,因此避免在每次循環(huán)中直接讀取HTML集合的length,容易導致死循環(huán)
使用節(jié)點的children屬性,而不是childNodes屬性,前者訪問速度更快,且不包含空白文本和注釋節(jié)點。
瀏覽器的渲染過程包括構(gòu)建DOM樹和渲染樹,當DOM元素的幾何屬性變化時,需要重新構(gòu)造渲染樹,這一過程稱為“重排”,完成重排后,瀏覽器會重新繪制受影響的部分到屏幕中,這一過程稱為“重繪”。因此應(yīng)該盡量合并多次對DOM的修改,或者先將元素脫離文檔流(display:none、文檔片段),應(yīng)用修改后,再插入文檔中。
每次瀏覽器的重排時都會產(chǎn)生消耗,大多數(shù)瀏覽器會通過隊列化修改并批量執(zhí)行來優(yōu)化重排過程,可當訪問元素offsetTop、scrollTop、clientTop、getComputedStyle等一系列布局屬性時,會強制瀏覽器立即進行重排返回正確的值。因此不要在dom布局信息改變時,訪問這些布局屬性。
當修改同個元素多個Css屬性時,可以使用CssText屬性進行一次性修改樣式,減少瀏覽器重排和重繪的次數(shù)
當元素發(fā)生動畫時,可以使用絕對定位使其脫離文檔流,動畫結(jié)束后,再恢復定位。避免動畫過程中瀏覽器反復重排文檔流中的元素。
多使用事件委托,減少監(jiān)聽事件
4.算法和流程控制
for循環(huán)和while循環(huán)性能差不多,除了for-in循環(huán)最慢(其要遍歷原型鏈)
循環(huán)中要減少對象成員及數(shù)組項的查詢次數(shù),可以通過倒序循環(huán)提高性能
循環(huán)次數(shù)大于1000時,可運用Duff Devices減少迭代次數(shù)
switch比if-else快,但如果具有很多離散值時,可使用數(shù)組或?qū)ο髞順?gòu)建查找表
遞歸可能會造成調(diào)用棧溢出,可將其改為循環(huán)迭代
如果可以,對一些函數(shù)的計算結(jié)果進行緩存
5.字符串和正則表達式
進行大量字符串的連接時,+和+=效率比數(shù)組的join方法要高
當創(chuàng)建了一個正則表達式對象時,瀏覽器會驗證你的表達式,然后將其轉(zhuǎn)化為一個原生代碼程序,用戶執(zhí)行匹配工作。當你將其賦值給變量時,可以避免重復執(zhí)行該步驟。
當正則進入使用狀態(tài)時,首先要確定目標字符串的起始搜索位置(字符串的起始位置或正則表達式的lastIndex屬性),之后正則表達式會逐個檢查文本和正則模式,當一個特定的字元匹配失敗時,正則表達式會試著回溯到之前嘗試匹配的位置,然后嘗試其他路徑。如果正則表達式所有的可能路徑都沒有匹配到,其會將起始搜索位置下移一位,重新開始檢查。如果字符串的每個字符都經(jīng)歷過檢查,沒有匹配成功,則宣布徹底失敗。
當正則表達式不那么具體時,例如.和[\s\S]等,很可能會出現(xiàn)回溯失控的情況,在js中可以應(yīng)用預查模擬原子組(?=(pattern))\1來避免不必要的回溯。除此之外,嵌套的量詞,例如/(A+A+)+B/在匹配"AAAAAAAA"時可能會造成驚人的回溯,應(yīng)盡量避免使用嵌套的量詞或使用預查模擬原子組消除回溯問題。
將復雜的正則表達式拆分為多個簡單的片段、正則以簡單、必需的字元開始、減少分支數(shù)量|,有助于提高匹配的效率。
setTimeout(function(){ process(todo.shift()); if (todo.length > 0) { setTimeout(arguments.callee, 25); } else { callback(); } })
setTimeout(function(){ let start = +new Date(); do { process(todo.shift()); } while(todo.length > 0 && (+new Date() - start) < 50) if (todo.length > 0) { setTimeout(arguments.callee, 25); } else { callback(); } })
WebWork
進行計算
Expires: Mon,28 Jul 2018 23:30:30 GMT
eval
、Function
進行雙重求值
Object
/Array
字面量定義,不要使用構(gòu)造函數(shù)
if (i & 1) { className = 'odd'; } else { className = 'even'; }
Math
對象等
藍藍設(shè)計的小編 http://www.wnxcall.com