js 防抖 節流 JavaScript

js 防抖 節流 JavaScript

實際工做中,經過監聽某些事件,如scroll事件檢測滾動位置,根據滾動位置顯示返回頂部按鈕;如resize事件,對某些自適應頁面調整DOM的渲染;如keyup事件,監聽文字輸入並調用接口進行模糊匹配等等,這些事件處理函數調用的頻率若是過高,會加劇瀏覽器的負擔,減弱性能,形成用戶體驗很差。此時須要採用debounce(防抖)和throttle(節流)的方式來減小調用頻率,同時不影響原來效果。javascript

函數防抖(debounce)

當持續觸發事件時,一段時間段內沒有再觸發事件,事件處理函數纔會執行一次,若是設定的時間到來以前就觸發了事件,延時從新開始。
函數防抖的應用場景,最多見的就是用戶註冊時候的手機號碼驗證和郵箱驗證了。只有等用戶輸入完畢後,前端才須要檢查格式是否正確,若是不正確,再彈出提示語。前端

clipboard.png

上圖中,持續觸發scroll事件時,並不執行handle函數,當1000毫秒內沒有觸發scroll事件時,纔會延時觸發scroll事件;
上面原理:對處理函數進行延時操做,若設定的延時到來以前,再次觸發事件,則清除上一次的延時操做定時器,從新定時。
代碼以下:java

// 函數防抖
var timer = false;
document.getElementById("debounce").onscroll = function(){
    clearTimeout(timer); // 清除未執行的代碼,重置回初始化狀態

    timer = setTimeout(function(){
        console.log("函數防抖");
    }, 1000);
};

防抖函數的封裝使用瀏覽器

/**
 * 防抖函數
 * @param method 事件觸發的操做
 * @param delay 多少毫秒內連續觸發事件,不會執行
 * @returns {Function}
 */
function debounce(method,delay) {
    let timer = null;
    return function () {
        let self = this,
            args = arguments;
        timer && clearTimeout(timer);
        timer = setTimeout(function () {
            method.apply(self,args);
        },delay);
    }
}
window.onscroll = debounce(function () {
    let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    console.log('滾動條位置:' + scrollTop);
},1000)

另外一種寫法app

// 防抖
function debounce(fn, wait) {    
    var timeout = null;    
    return function() {        
        if(timeout !== null)   clearTimeout(timeout);        
        timeout = setTimeout(fn, wait);    
    }
}
// 處理函數
function handle() {    
    console.log("函數防抖"); 
}
// 滾動事件
window.addEventListener('scroll', debounce(handle, 1000));

函數節流(throttlo)

當持續觸發事件時,保證必定時間段內只調用一次事件處理函數。
函數節流應用的實際場景,多數在監聽頁面元素滾動事件的時候會用到。函數

clipboard.png

上圖中,持續觸發scroll事件時,並不當即執行handle函數,每隔1000毫秒纔會執行一次handle函數;
函數節流的要點是,聲明一個變量當標誌位,記錄當前代碼是否在執行。若是空閒,則能夠正常觸發方法執行。
代碼以下:性能

// 函數節流 定時器
var canRun = true;
document.getElementById("throttle").onscroll = function(){
    if(!canRun){
        // 判斷是否已空閒,若是在執行中,則直接return
        return;
    }

    canRun = false;
    setTimeout(function(){
        console.log("函數節流");
        canRun = true;
    }, 300);
};

節流函數的封裝使用this

//節流throttle代碼(時間戳)
var throttle = function(func, delay) {            
  var prev = Date.now();            
  return function() {                
    var context = this;                
    var args = arguments;                
    var now = Date.now();                
    if (now - prev >= delay) {                    
      func.apply(context, args);                    
      prev = Date.now();                
    }            
  }        
}        
function handle() {            
  console.log("函數節流");        
}        
window.addEventListener('scroll', throttle(handle, 1000));


//節流throttle代碼(定時器)
var throttle = function(func, delay) {            
    var timer = null;            
    return function() {                
        var context = this;               
        var args = arguments;                
        if (!timer) {                    
            timer = setTimeout(function() {                        
                func.apply(context, args);                        
                timer = null;                    
            }, delay);                
        }            
    }        
}        
function handle() {            
    console.log("函數節流");        
}        
window.addEventListener('scroll', throttle(handle, 1000));


// 節流throttle代碼(時間戳+定時器):
var throttle = function(func, delay) {     
    var timer = null;     
    var startTime = Date.now();     
    return function() {             
        var curTime = Date.now();             
        var remaining = delay - (curTime - startTime);             
        var context = this;             
        var args = arguments;             
        clearTimeout(timer);              
        if (remaining <= 0) {                    
            func.apply(context, args);                    
            startTime = Date.now();              
        } else {                    
            timer = setTimeout(func, remaining);              
        }      
    }
}
function handle() {      
    console.log("函數節流");
} 
window.addEventListener('scroll', throttle(handle, 1000));

用時間戳+定時器,當第一次觸發事件時立刻執行事件處理函數,最後一次觸發事件後也還會執行一次事件處理函數spa

歡迎關注

相關文章
相關標籤/搜索