JS的防抖、節流函數

防抖、節流函數通常應用在一些高頻觸發的方法,例如搜索框聯想輸入的input事件、onmousemove事件、click事件等等;實際上業務不須要屢次觸發,那麼就須要用到防抖或者節流來處理啦。javascript

簡單的能夠這樣理解java

防抖函數:瘋狂點擊按鈕,每次點擊的時間間隔都小於規定時間,那麼相應的方法不會執行閉包

節流函數:瘋狂點擊按鈕,規定的時間間隔內只觸發一次相應的方法app

是否當即執行的區別就是,當即執行執行的是第一次觸發的狀態,非當即執行觸發的是最後一次的狀態dom

防抖

代碼

let Debounce = function (fn, delay = 300, immediate = false) {
    let timer = null // 閉包存儲setTimeout狀態
    return function () {
        let self = this // 事件源this
        let args = arguments // 接收事件源的event
        if (timer) clearTimeout(timer) // 存在就清除執行fn的定時器
        if (immediate) { // 當即執行
            let callNow = !timer // 執行fn的狀態
            timer = setTimeout(function () {
                timer = null
            }, delay)
            if (callNow) fn.apply(self, args)
        } else { // 非當即執行
            timer = setTimeout(function () { // 或者使用箭頭函數將this指向dom
                fn.apply(self, args)
            }, delay)
        }
    }
}

let con1 = document.querySelector('.con1')
let con2 = document.querySelector('.con2')
let con3 = document.querySelector('.con3')

let addNum = function (args) {
    console.log(this, args)
    this.innerText = (+this.innerText) + 1
}

con1.onmousemove = addNum // 無防抖

con2.onmousemove = Debounce(addNum) // 防抖

con3.onmousemove = Debounce(addNum, 300, true) // 防抖(當即執行)
複製代碼

效果對比

節流

代碼

// 基礎版節流
let Throttle = function (fn, delay = 500) {
    let flag = true
    return function () {
        let self = this
        let args = [...arguments]
        if (!flag) return
        flag = false
        setTimeout(function () {
            fn.apply(self, args)
            flag = true
        }, delay)
    }
}

let con1 = document.querySelector('.con1')
let con2 = document.querySelector('.con2')

let addNum = function (args) {
    console.log(this, args)
    this.innerText = (+this.innerText) + 1
}

con1.onmousemove = addNum // 無節流

con2.onmousemove = Throttle(addNum, 1000) // 節流
複製代碼

效果對比

節流函數的另外一種寫法,防抖函數也能夠使用時間戳做爲判斷條件函數

// 時間間隔做爲判斷
let ThrottleTime = function (fn, delay = 500) {
    let preTime = 0 // 記錄上一次執行時間
    return function () {
        let self = this, // 保留執行時候的的this
            args = [...arguments], // 執行時候的傳入參數
            nowTime = +new Date() // 記錄當前的時間
        if (nowTime - preTime >= delay) {
            preTime = nowTime // 更新執行時間
            fn.apply(self, args)
        }
    }
}
複製代碼

加上當即執行狀態ui

// 是否當即執行
let ThrottlePro = function (fn, delay = 500, immediate = false) {
    let preTime = 0 // 記錄上一次執行時間
    return function () {
        let self = this, // 保留執行時候的的this
            args = [...arguments], // 執行時候的傳入參數
            nowTime = +new Date(), // 記錄當前的時間
            flag = nowTime - preTime >= delay // 執行命令
        if (immediate) { // 是否當即執行
            if (!flag) return
            preTime = nowTime // 更新執行時間
            fn.apply(self, args)
        } else {
            if (!flag) return // 不知足執行條件
            preTime = nowTime
            setTimeout(function () {
                fn.apply(self, args)
            }, delay)
        }
    }
}
複製代碼

相關文章
相關標籤/搜索