JavaScript淺析 -- 定時器和節流防抖
一、定時器
js的定時器主要有setTimeout和setInterval兩個,下面我們分別講講。
1. setTimeout
setTimeout()設定任務延遲多久之後才執行,該函式第一個引數可以是可執行語句(字串形式)或者一個函式,第二個引數是延遲的毫秒數(若省略則預設為0),後續的引數則代表第一個函式的引數。
// 下面兩者一樣
setTimeout('console.log(666)',1000);
setTimeout(function() {
console.log(666);
}, 1000);
setTimeout('console.log(666)'); // 相當於setTimeout('console.log(666)', 0);
setTimeout(function(a, b) {
console.log(a + b); // 3
}, 1000, 1, 2);
其中有兩點要注意(具體原因可以看這篇文章):
- 函式裡面的this指向的是全域性,因為賦值的是函式的地址,執行的時候是從任務佇列取出來在主執行棧中全域性呼叫。
var obj = {
y: function () {
console.log(this);
}
};
setTimeout(obj.y, 1000) // window
- 定時器設定的毫秒數是理想情況下多少毫秒後執行,但實際情況下是可能多於該毫秒數之後才執行。因為雖然數完秒就放到任務佇列,但要等主執行棧為空了才會去呼叫這些任務佇列的回撥函式。
// 下面的雖然寫了1s後執行輸出666,但實際卻要3s後才執行輸出666
setTimeout('console.log(666)', 1000);
function execTime(t) {
var start = Date.now();
while(Date.now() - start < t) {}
}
execTime(3000);
2. setInterval
setInterval與setTimeout用法和注意點基本差不多,他主要用於設定時間間隔,每隔多少毫秒之後重複執行任務,直到瀏覽器關閉或手動清除。
實際上,兩次函式執行的間隔時間也不是所設定的毫秒數,而是小於執行的毫秒數的,比如設定了100ms,第一次函式執行用了10ms,那麼間隔90ms之後第二次執行函式;如果第一次函式執行用了110ms,那麼函式執行完畢之後會立馬執行第二次函式。那如果要固定間隔時間執行某函式,可以用setTimeout來模擬。
var timer = setTimeout(function f() {
// ...
timer = setTimeout(f, 2000);
}, 2000);
3. 清除定時器
setTimeout和setInterval生成的都是計數器編號,從0開始,將對應的編號傳入clearTimeout和clearInterval就可以清除對應的定時器。
var a = 0;
var timer = setInterval(function() {
console.log(a++); // 輸出0、1就停了
if (a===2) {
clearInterval(timer);
}
}, 1000);
當瀏覽器的標籤頁開啟之後,每生成一個定時器都是從上一個編號開始累加上去的,第一個定時器編號是0,第二個是1,如此類推,所以清除所有的定時器可以這麼實現。
var timer = setTimeout(function(){}, 0);
while(timer >= 0) {
clearTimeout(timer);
timer--;
}
二、節流和防抖
通過定時器,我們可以實現函式節流和函式防抖。
1. 函式節流
函式節流指的是在規定時間內重複觸發不重複執行,以節流。如監聽頁面滾動到底的時候載入新的資料,但往往會連續觸發滾動事件導致連續發起幾次請求,此時就需要函式節流。
function throttle(fn, delay) {
var isFinished = true;
return function() {
if (!isFinished) return;
isFinished = false;
var that = this, args = arguments;
setTimeout(function() {
fn.apply(that, args);
isFinished = true;
}, delay);
};
}
document.onscroll = throttle(function() { /* 請求資料 */ }, 20);
正如上面的程式碼,函式節流主要是鎖的思想。先執行一次,當上一個執行完畢才解鎖isFinished = true
,否則鎖住isFinished = false
程式碼不讓執行。
2. 函式防抖
函式防抖指的是規定時間內重複觸發只執行最後一次,以防止頻繁觸發帶來的抖動。如輸入框搜尋時,如果每當輸入框有一個字變化就搜尋,一是對頻繁請求對伺服器壓力大,二是前端也會頻繁的閃現搜尋的結果,使用者體驗不好。所以一般都會有個延時,等使用者輸入延遲一段時間後確定不再輸入再進行搜尋。
function debounce(fn, delay) {
var timer = null;
return function() {
clearTimeout(timer);
var that = this, args = arguments;
setTimeout(function() {
fn.apply(that, args);
}, delay);
};
}
document.querySelector('input').onchange = debounce(function() { /* 請求資料 */ }, 200);
函式防抖的主要思想是定時器清除。規定時間內再次觸發,則上一個未被執行的定時器被清除,再開啟新的定時器,直到最後一次觸發。
上面寫的是兩個簡單版本的函式節流和函式防抖,主要是為了講解兩者的主要思想,也好進行區分:
- 節流是先執行一次,然後過規定時間之後才能再執行。防抖是過了規定時間之後沒再觸發,最後執行一次。
- 節流是鎖的思想,防抖是清除定時器的思想。
- 注意最後返回結果都是函式,而且要注意函式中的this指向是返回函式的this。
相關文章
- 淺談JavaScript的防抖與節流JavaScript
- 防抖和節流
- 淺談 JavaScript 中的防抖與節流(一)JavaScript
- JavaScript專題系列-防抖和節流JavaScript
- JavaScript之節流與防抖JavaScript
- 筆記-JavaScript[節流][防抖]筆記JavaScript
- js防抖和節流JS
- JavaScript中函式防抖、節流JavaScript函式
- 淺聊函式防抖與節流函式
- 函式防抖和節流函式
- 防抖和節流原理分析
- 函式節流和防抖函式
- 淺談js函式節流和函式防抖JS函式
- javascript之函式防抖與節流JavaScript函式
- 前端戰五渣學JavaScript——防抖、節流和rAF前端JavaScript
- js 函式防抖和節流JS函式
- 函式的防抖和節流函式
- js防抖 和節流函式JS函式
- 節流防抖封裝封裝
- UnderScore原始碼看防抖和節流原始碼
- 效能優化之防抖和節流優化
- 函式防抖和函式節流函式
- 固定表頭和首列,防抖節流
- JavaScript中的防抖與節流-圖文版JavaScript
- js函式防抖debounce和節流throttleJS函式
- 防抖動處理和節流 小技巧
- JS函式節流和函式防抖JS函式
- js函式中的節流和防抖JS函式
- JS簡單實現防抖和節流JS
- 蝦扯蛋之函式防抖和節流函式
- 例項解析防抖動和節流閥
- JavaScript 高階系列之節流 [throttle] 與防抖 [debounce]JavaScript
- 函式的防抖與節流函式
- 當Flutter遇到節流與防抖Flutter
- js優化之防抖節流JS優化
- 【跟著大佬學JavaScript】之lodash防抖節流合併JavaScript
- 防抖和節流的應用場景和實現
- 前端都應該要掌握的防抖和節流前端