1. 程式人生 > >防抖和節流的實現

防抖和節流的實現

防抖

  • 觸發函式後多長時間沒再次觸發,執行一次函式,如果再次觸發重新開始計時
  • 常用於 key resize 等高頻事件,輸入框輸入值時的本地快取和非同步請求
// 當頁面發生滾動的時1s後執行函式
var timer = null;
window.addEventListener('scroll', function() {
    if(timer) clearTimeout(timer);
    timer = setTimeout(function() {
        console.log('我是a函式');
    }, 1000)
});

// 把函式抽出來
var timeout = null;
function debounce() {
    if(timeout) clearTimeout(timeout);
    timeout = setTimeout(function() {
        console.log('我是a函式');
    }, 1000)
}
window.addEventListener('scroll', debounce);

// 消除全域性變數timeout
function debounce(fn, delay) {
    var timeout = null;
    return function() {
        if(timeout !== null) clearTimeout(timeout);
        timeout = setTimeout(fn, delay);
    }
}
function aa(){
    console.log('我是a函式')
}
window.addEventListener('scroll', debounce(aa, 1000));

// 消除區域性變數timeout
function debounce(fun, delay) {
    return function() {
        let that = this;
        clearTimeout(fun.id)
        fun.id = setTimeout(function() {
            fun.call(that)
        }, delay)
    }
} 

window.addEventListener('scroll', debounce(aa, 1000));

// es6語法 減少區域性變數
function debounce(fun, delay) {
    return function() {
        clearTimeout(fun.id)
        fun.id = setTimeout(() => {fun()}, delay)
    }
} 
window.addEventListener('scroll', debounce(aa, 1000));
  • input輸入觸發事件的例子,增加引數傳遞
//模擬一段ajax請求
function ajax(content) {
  console.log('ajax request ' + content)
}

function debounce(fun, delay) {
    return function (args) {
        let that = this
        let _args = args
        clearTimeout(fun.id)
        fun.id = setTimeout(function () {
            fun.call(that, _args)
        }, delay)
    }
}
    
let inputb = document.getElementById('debounce')

// 變數賦值
let debounceAjax = debounce(ajax, 500)

inputb.addEventListener('keyup', function (e) {
    debounceAjax(e.target.value)
})

節流

  • 規定多少時間內執行一次函式
  • 常用於click,scroll事件,監聽是否滑動到底部載入更多
  • 節流實現的方式有兩種時間戳和定時器
// 1. 時間戳的方式  特點:第一次觸發 立即執行
var throttle = function(func, delay) {
    var prev = Date.now();
    return function() {
        var that = this;
        var args = arguments;
        var now = Date.now();
        if(now - prev >= delay) {
            func.apply(that, args);
            prev = Date.now();
        }
    }
}

function aa() {
    console.log('我是aa函式');
}
window.addEventListener('scroll', throttle(aa, 1000));
// 2. 定時器方式 特點:第一次不會立即執行,最後一次會延遲執行
var throttle = function(func, delay) {
    var timer = null;
    return function() {
        var that = this;
        var args = arguments;
        if(!timer) {
            timer = setTimeout(function() {
                func.apply(that, args);
                timer = null;
            }, delay);
        }
    }
}

function aa() {
    console.log('我是aa函式');
}
window.addEventListener('scroll', throttle(aa, 1000));
// 3. 時間戳+定時器  第一次會立即執行,最後一次會延遲執行
var throttle = function(func, delay) {
    var timer = null;
    var startTime = Date.now();
    return function() {
        var curTime = Date.now();
        var remaining = delay - (curTime - startTime);
        var that = this;
        var args = arguments;
        clearTimeout(timer);
        if(remaining <= 0) {
            func.apply(that, args);
            startTime = Date.now();
        } else {
            timer = setTimeout(func, remaining);
        }
    }
}

參考

掘金-7分鐘理解JS的節流、防抖及使用場景
節流