運行在瀏覽器中的JavaScript都被分配了一個肯定數量的資源,不一樣於桌面應用每每可以隨意控制他們要的內存大小和處理時間,Javascript被嚴格限制了,以防止惡意的Web程序員吧用的計算機搞掛了,其中一個限制是長時間運行腳本的制約,若是代碼運行超過特定時長或者特定數量的語句就不讓它繼續執行,詢問是容許其繼續執行仍是中止它。全部JavaScript開發人員的目標就是,確保用戶永遠不會再瀏覽器中看到這個使人費解的對話框。定時器是繞開此限制的方法之一javascript
腳本運行時間長的2個緣由:css
1.過長的、過深嵌套的函數調用;html
2.進行大量處理的循環;java
這2種後者較爲容易的被解決jquery
進行大量處理的循環:程序員
使用這種方式必須知足的要求:bootstrap
1.該處理不是必須同步完成數組
2.數據不是必須按順序完成瀏覽器
解決方案:數組分塊markdown
function chunk(arr, process, context){ setTimeout(function () { var item = arr.shift() process.call(context, item) if(arr.length > 0){ setTimeout(arguments.callee, 100) } }, 100) }
使用場景建議:
一旦某個函數的執行須要花50ms以上的時間完成,那麼最好看看可否將任務分割爲一系列可使用定時器的小任務。
1.4.1 節流函數的起源
瀏覽器中的某些計算和處理要比其餘的開銷大不少。例如,DOM比起非DOM交互須要更多的內存和CUP時間。連續嘗試進行過多的DOM相關操做可能會致使瀏覽器掛起,有時候甚至奔潰。尤爲在IE中使用onresize時處理程序的時候很容易發生,當調整瀏覽器大小的時候,該事件會連續觸發。在onresize事件處理程序內部若是嘗試進行DOM操做,其高頻率的更改可能會讓瀏覽器奔潰。爲了繞開這個問題,可使用定時器對該函數進行節流。
1.4.2 節流函數的原理
某段代碼不能在沒有間隔的狀況下連續重複執行。
第一次調用函數,建立一個定時器,在指定的時間間隔後執行代碼,當第二次調用該函數時,他會清除前一次的定時器並設置另外一個定時器。若是前一個定時器已經執行了,這個操做沒有任何意義。而後,若是前一個定時器還沒有執行,其實就是將其替換爲一個新的定時器。目的只有一個:只有在執行函數的請求中止了一段時間以後才執行。
1.4.3 適合節流的場景:週期性執行的代碼
1.4.4 節流函數的實現
var processor = { timeoutId: null, performProcessing: function () { //實際執行的代碼 }, process: function () { clearTimeout(this.timeoutId) var that = this this.timeoutId = setTimeout(function () { that.performProcessing() }, 100) } }
1.4.5 節流函數實現的簡化
function throttle (cb, context) { clearTimeout(cb.ID) cb.ID = setTimeout(function () { cb.call(context) }, 1000) }
給瀏覽器設置節流和延遲:使出現的效果可以在本身被本身察覺。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> h1 { color: red!important; } </style> <script> function h () { let h1 = document.getElementById('h1') console.log( h1 ) } setTimeout(h, 0) </script> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css"> </head> <body> <h1 id="h1">這是紅色</h1> </body> </html>
結果:在css正在下載時,h1標籤被控制太打印出來,可是頁面沒有文字。
結論:css加載會阻塞DOM樹渲染,不會阻塞DOM樹的解析。
我的見解:這樣子作仍是符合優化的正常邏輯的,css不會阻塞解析;若是不阻塞css渲染,等這個css加載完成後,會觸發迴流和重繪額外增長性能開銷,因此還不如直接等css加載完成後再來渲染。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> h1 { color: red!important; } </style> <script> console.log('before css') var startDate = new Date() </script> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css"> </head> <body> <h1 id="h1">這是紅色</h1> <script> var endData = new Date() console.log('after css') console.log('已通過了' + (endData - startDate)) </script> </body> </html>
結果:在css正在加載時,控制檯內容:before css
css加載完成時,控制檯內容:
before css after css 已通過了3444
結論:css加載時,會阻塞js的執行。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.min.js"></script> <script> console.log(1111) </script> <style> h1 { color: red!important; } </style> </head> <body> <h1 id="h1">這是紅色</h1> </body> </html>
現象:Loading js時,後續js沒有執行,後續DOM沒有解析。