js的防抖与节流

这篇具有很好参考价值的文章主要介绍了js的防抖与节流。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

认识防抖与节流

JavaScript中,大量操作都会触发事件,这些事件又会被添加到事件队列中进行排队处理
某些事件如果频繁触发的话会对浏览器的性能造成损耗,我们就可以使用防抖或者节流操作来限制事件的执行频率

防抖

防抖即当一个事件被触发时不会立即执行,而是会等待一段时间后执行,在等待期间如果此事件被重复触发,则等待时间也会重新计算,只有在等待期间内没有事件触发,等待时间结束后才会触发事件的回调函数
简单地说,王者里的回城就是一种防抖

节流

节流即当事件触发时会执行事件的回调函数,之后这个事件将会等待一段时间,在这段时间内触发的事件都将不会执行,直到等待时间结束后如果依旧此事件触发才会执行此事件的回调函数,之后继续等待
简单地说,王者里的技能就是一种节流

如下图所示
js的防抖与节流,网页,javascript,前端,开发语言

手写防抖函数

const debounce = (fn, delay) => {
    let timer = null
    return () => {
        timer && clearTimeout(timer)
        timer = setTimeout(fn, delay)
    }
}
const resize = debounce(() => {
    console.log('resize')
}, 1000)
window.addEventListener('resize', resize)

结果如下
js的防抖与节流,网页,javascript,前端,开发语言
但这个函数十分简陋,没有绑定this,也没有参数传递,接下来我们一步一步来实现这些功能

绑定this与参数

绑定this有两种方式,一种是通过在参数列表中传入this指向,然后通过显式绑定到对应的对象上,还有一种是将返回的箭头函数改成普通函数

  1. 第一种方式
const debounce = (fn, {delay,that}={}) => {
    let timer = null
    return () => {
        timer && clearTimeout(timer)
        timer = setTimeout(fn.apply(that), delay)
    }
}
const resize = debounce(() => {
    console.log(this)

}, {
    delay:1000,
    that:window
})
window.addEventListener('resize', resize)

这段代码粗看似乎没什么问题,但实测发现防抖函数无效,因为apply会立即调用函数,解决方法是将apply封装到一个函数中

const debounce = (fn, { delay, that } = {}) => {
    let timer = null
    return () => {
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(that)
        }, delay)
    }
}
const resize = debounce(() => {
    console.log(this)

}, {
    delay: 1000,
    that: window
})
window.addEventListener('resize', resize)

当我们需要传递的参数过多时可以通过参数解构与默认值的方式获取
2. 第二种方式

const debounce = (fn, delay) => {
    let timer = null
    return function () {
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this)
        }, delay)
    }
}
const resize = debounce(() => {
    console.log(this)

}, 1000)
window.addEventListener('resize', resize)

最后结果都是一样的
js的防抖与节流,网页,javascript,前端,开发语言
参数的绑定十分简单,这里就不再赘述了

const debounce = (fn, delay) => {
    let timer = null
    return function (...args) {
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, args)
        }, delay)
    }
}
const resize = debounce((event) => {
    console.log(this, event)
}, 1000)
window.addEventListener('resize', resize)

取消功能

有时候事件触发了但我们之后又不想函数执行,可以增加一个取消功能,我们可以在返回的函数上直接添加一个属性cancel

const debounce = (fn, delay) => {
    let timer = null
    const _debounce = function (...args) {
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, args)
        }, delay)
    }
    _debounce.cancel = function () {
        timer && clearTimeout(timer)
    }
    return _debounce
}
const resize = debounce((event) => {
    console.log(this, event)
}, 1000)
window.addEventListener('resize', resize)

立即执行

立即执行即我们需要在事件触发时的第一次就执行函数

const debounce = (fn, { delay = 1000, immediate = false } = {}) => {
    let timer = null
    let isInvoke = false

    const _debounce = function (...args) {
        if (immediate && !isInvoke) {
            fn.apply(this, args)
            isInvoke = true
            return
        }
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, args)
        }, delay)
    }
    _debounce.cancel = function () {
        timer && clearTimeout(timer)
    }
    return _debounce
}
const resize = debounce((event) => {
    console.log(this, event)
}, {
    delay: 1000,
    immediate: true
})
window.addEventListener('resize', resize)

js的防抖与节流,网页,javascript,前端,开发语言

获取返回值

有时候我们在手动调用防抖函数的时候需要得到函数的返回值就可以这么写,第一种方案是通过回调函数,第二种则是返回一个Promise

  1. 传入一个回调函数来获取返回值
const debounce = (fn, { delay = 1000, immediate = false, callback } = {}) => {
    let timer = null
    let isInvoke = false

    const _debounce = function (...args) {
        if (immediate && !isInvoke) {
            fn.apply(this, args)
            isInvoke = true
            return
        }
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
            let res = fn.apply(this, args)
            callback && callback(res)
        }, delay)
    }
    _debounce.cancel = function () {
        timer && clearTimeout(timer)
    }
    return _debounce
}
const resize = debounce((event) => {
    console.log(this)
    return "resize return"
}, {
    delay: 1000,
    immediate: false,
    callback: (res) => {
        console.log(res)
    }
})
resize()
  1. 返回一个Promise得到返回值
const debounce = (fn, { delay = 1000, immediate = false } = {}) => {
    let timer = null
    let isInvoke = false

    const _debounce = function (...args) {
        return new Promise((resolve, reject) => {
            if (immediate && !isInvoke) {
                fn.apply(this, args)
                isInvoke = true
                return
            }
            timer && clearTimeout(timer)
            timer = setTimeout(() => {
                let res = fn.apply(this, args)
                resolve(res)
            }, delay)
        })
    }
    _debounce.cancel = function () {
        timer && clearTimeout(timer)
    }
    return _debounce
}
const resize = debounce((event) => {
    console.log(this)
    return "resize return"
}, {
    delay: 1000,
    immediate: false
})
resize().then((res) => {
    console.log(res)
})

结果都是一样的
js的防抖与节流,网页,javascript,前端,开发语言

最终版

最后我们将以上代码优化一下就得到了最终版本的防抖函数

const debounce = (fn, { delay = 1000, immediate = false } = {}) => {
    let timer = null
    let isInvoke = false

    const _debounce = function (...args) {
        return new Promise((resolve, reject) => {
            try {
                if (immediate && !isInvoke) {
                    let res = fn.apply(this, args)
                    isInvoke = true
                    resolve(res)
                    return
                }
                timer && clearTimeout(timer)
                timer = setTimeout(() => {
                    let res = fn.apply(this, args)
                    timer = null
                    isInvoke = false
                    resolve(res)
                }, delay)
            } catch (error) {
                reject(error)
            }
        })
    }
    _debounce.cancel = function () {
        timer && clearTimeout(timer)
        isInvoke = false
        timer = null
    }
    return _debounce
}

手写节流函数

节流函数在实现上和防抖函数稍有不同,不通过定时器而是通过时间戳
以下是一个简略的节流函数实现

const throttle = (fn, { wait = 1000, }) => {
    let preTime = 0;
    const _throttle = function (...args) {
        let nowTime = Date.now();
        if (nowTime - preTime > wait) {
            fn.apply(this, args);
            preTime = nowTime;
        }
    }
    return _throttle
}
const resize = throttle(function () {
    console.log("resize")
}, {
    wait: 1000,
})
window.addEventListener('resize', resize)

结果如下
js的防抖与节流,网页,javascript,前端,开发语言

节流函数的优化

至于节流函数的一些优化:

  1. 节流函数立即执行与尾部执行
  2. 添加取消功能
  3. 获得返回值

与防抖函数的思路大差不差,这里就不再过多赘述,以下是完全版文章来源地址https://www.toymoban.com/news/detail-801056.html

const throttle = (fn, { wait = 1000, leading = true, trailing = false } = {}) => {
    let preTime = 0;
    let timer
    const _throttle = function (...args) {
        return Promise((resolve, reject) => {
            try {
                let nowTime = Date.now();
                if (!leading && preTime == 0) {
                    preTime = nowTime
                }
                let interval = wait - (nowTime - preTime)
                if (interval <= 0) {
                    let res = fn.apply(this, args)
                    resolve(res)
                    if (timer) clearTimeout(timer)
                    preTime = nowTime
                    timer = null
                    return
                }
                if (trailing && !timer) {
                    timer = setTimeout(() => {
                        let res = fn.apply(this, args)
                        resolve(res)
                        preTime = Date.now()
                        timer = null
                    }, interval)
                }
            } catch (error) {
                reject(error)
            }
        })
    }
    _throttle.cancel = function () {
        if (timer) clearTimeout(timer)
        preTime = 0
        timer = null
    }
    return _throttle
}

到了这里,关于js的防抖与节流的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 消灭前端闪烁魔鬼:Vue中的防抖术

    在前端的世界里,用户操作如同一场狂风骤雨,而我们的页面则要顶住这些波澜汹涌的输入。有时候,我们希望页面在用户输入停止后再作出响应,以避免频繁触发操作。这时,Vue的防抖动技术就如同时光隧道一样,将我们带回到宁静的过去。 本篇博客将带你穿越时空,揭开

    2024年02月02日
    浏览(33)
  • js中如何实现一个简单的防抖函数?

    前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供一

    2024年02月09日
    浏览(35)
  • 在JavaScript中的防抖函数 - 通过在React中构建自动完成功能来解释

    当你将一个新应用推向生产环境时,你希望确保它用户友好。网站的性能是用户体验的关键部分。每个用户都希望网站及其内容能够快速加载。每一秒都是宝贵的,可能导致用户再也不会访问你的网站。 在本指南中,我们将了解JavaScript中一个非常重要的技术,即防抖函数。

    2024年02月19日
    浏览(34)
  • JS—节流与防抖

    一、js防抖和节流 在进行窗口的resize、scroll、输出框内容校验等操纵的时候,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常之差。那么为了前端性能的优化也为了用户更好的体验,就可以采用防抖(debounce)和节流(throttle)的方式来到达这种

    2023年04月08日
    浏览(31)
  • javascript常见100问|前端基础知识|问ajax-fetch-axios-区别请用 XMLHttpRequestfetch 实现 ajax节流和防抖px em rem vw/箭头函数的缺点

    HTML CSS JS HTTP 等基础知识是前端面试的第一步,基础知识不过关将直接被拒。本章将通过多个面试题,讲解前端常考的基础知识面试题,同时复习一些重要的知识点。 扎实的前端基础知识,是作为前端工程师的根本。基础知识能保证最基本的使用,即招聘进来能干活,能产出

    2024年04月27日
    浏览(38)
  • 前端优化 ----防抖 节流

    如果一个事件在短时间内连续触发,则只去执行最后一次。 控制频率 实现方式:每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法 缺点:如果事件在规定的时间间隔内被不断的触发,则调用方法会被不断的延迟 使一个函数在固定时间内只执行一次。控制

    2024年02月04日
    浏览(27)
  • 前端刷题-防抖节流

    在实际的开发过程中,一般会使用lodash自有的debounce函数和throttle函数对所要防抖/节流的函数进行包裹。例如

    2024年02月10日
    浏览(28)
  • 【前端】防抖和节流原理+实现

    防抖(Debounce)和节流(Throttle)都是用于控制函数执行频率的机制,它们在处理高频触发的事件时非常有用。 防抖的原理是在事件被触发后,等待一段时间(例如200毫秒)来执行函数,如果在等待时间内事件被再次触发,则重新计时。这样可以避免在短时间内多次触发事件

    2024年04月16日
    浏览(24)
  • 节流防抖:提升前端性能的秘密武器(上)

    🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入

    2024年02月04日
    浏览(32)
  • 【js】防抖和节流的使用场景和区别:

    一、防抖 (多次触发 只执行最后一次) 作用: 高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间内再次触发,则重新计算时间 防抖类似于英雄联盟回城6秒,如果回城中被打断,再次回城需要再等6秒 二、节流 (规定时间内 只触发一次) 作用:

    2024年02月10日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包