實際上,瀏覽器負責進行排序,指派某段代碼在某個時間點運行的優先級。
可以吧js想象成在時間線上運行的。
JavaScript中沒有任何代碼是立刻執行的,但一旦進程空閑則盡快執行。
1.重復的定時器:
setInterval()的重復定時器存在兩個缺點:
(1)某些間隔會被跳過
(2)多個定時器的代碼執行之間的間隔可能比預期的小;
假設,某個onclick事件處理程序使用setInterval()設置了一個200ms間隔的重復定時器。如果事件處理程序花了300ms多一點的時間完成,同時定時器代碼也花了差不多的時間,就會同時出現跳過間隔且連續運行定時器代碼的情況。
為了避免這個缺點,可以使用鏈式setTimeout()調用。
setTimeout(function() {
setTimeout(arguments.callee, interval);
},interval)
callee是arguments的一個屬性,指的是對函數對象本身的引用。
2.Yielding Processes
運行在瀏覽器中的JavaScript都被分配了一個確定數量的資源。
腳本長時間運行的問題通常是由兩個原因之一造成的:
(1)過長的、過深嵌套的函數調用。
(2)進行大量處理的循環。
for (var i = 0,len=data.length; i < len; i++) {
process(data[i]);
};
process要花100ms,那么總的花費時間是由數組的長度決定的。JavaScript的執行是一個阻塞操作,腳本運行花費的時間越久,用戶無法與頁面交互的時間也越久。
解決這個問題有一種技術叫做:數組分塊
小塊小塊地處理數組,通常每次一小塊。
基本的思路是為要處理的項目創建一個小隊列,然后使用計時器取出下一個要處理的項目進行處理,接着再設置另一個定時器。
1 function chunk(array, process, context) { 2 setTimeout(function(){ 3 var item = array.shift(); 4 process.call(context, item); 5 6 if (array.length>0) { 7 setTimeout(arguments.callee, 100); 8 }; 9 }, 100) 10 }; 11 12 var data = [12,12,1234,453,436,23,23,5,4123,45,346,3563,2234,345,342]; 13 14 function printValue(item) { 15 var div = document.getElementById('myDiv'); 16 div.innerHTML += item + "</br>"; 17 }; 18 chunk(data.concat(), printValue);
chunk方法接收三個參數:要處理的項目的數組,用於處理項目的函數,運行該函數的環境。這個函數用來處理數組。
調用chunk時,為了不改變數組原來的值,用到了一個concat方法:(返回一個新的數組,此方法里面可以添加參數。這些參數和調用的數組組成一個新的數組。)。由於printValue函數處在全局作用域內,因此無需給chunk()傳遞一個context對象。
3.函數節流:
函數節流的思想是:某些代碼不可以在沒有間斷的情況下連續重復執行。
第一次調用函數,創建一個定時器,在指定的時間間隔后運行代碼。當第二次調用該函數時,它會清除前一次的定時器並設置另一個。
function printValue(item) {
var div = document.getElementById('myDiv');
div.innerHTML += item + "</br>";
};
chunk(data.concat(), printValue);
// 函數節流
function throttle(method, context) {
clearTimeout(method.tId);
method.tId = setTimeout(function(){
method.call(context);
}, 100)
};
function resizeDiv() {
var div = document.getElementById('myDiv');
div.style.height = div.offsetWidth + "px";
};
window.onresize = function() {
throttle(resizeDiv);
};
throtttle函數用來進行函數節流:這個函數首先清除之前設置的定時器。然后定義定時器,在100ms后再執行method方法(method.call(context)是為了確保方法在適當的環境中執行)。如果這個throttle在100ms內執行了50次,那么method方法也只會執行一次。(這就是節流)
window.onresize方法會造成瀏覽器運行緩慢的兩個原因:
(1)首先,要計算offsetWidth屬性,如果該元素或者頁面上其他元素有非常復雜的css樣式,那么整個過程將會很復雜。
(2)其次,設置某個元素的高度需要對頁面進行回流來令改動生效。如果頁面有很多元素同時應用了相當數量的css的話,這個又需要很多的計算。
只要代碼是周期性執行的,都應該使用節流,但是你不能控制請求的執行的效率。可以改動throttle函數的時間間隔。
