JS 函数防抖与节流

防抖throttle

防抖:当事件在短时间内持续触发,在间隔时间内(如1000ms),只在最后一次触发的时候,执行目标函数。

就是说,防抖不会让函数立即执行,而是1000ms延时内没有再次触发,才会执行目标函数
实现:通过setTimeout做延时处理,如果定时器不为空,则重新延时。
应用场景:监听输入框keyup。

//防抖
function debounce(fn,delay){
    let timer = null   //借助闭包
    return function() {
        if(timer){
            clearTimeout(timer) 
        }
        timer = setTimeout(fn,delay)   // 简化写法
    }
}
//目标函数
function handle(){
  console.log(Math.random())
}
//监听防抖
window.onscroll = debounce(handle,1000)

以上代码的效果就是,在滚动条停止一秒滚动之后,才会执行一次函数,输出一个随机数。

节流debounce

节流:函数间隔一段时间后才能再触发,避免某些函数触发频率过高。

就是说,保证目标函数在间隔时间(如1000ms)内只执行一次
实现:一定时间内只触发一次函数,通过判断是否达到一定时间来确定是否要执行目标函数。
应用场景:防止频繁点击造成表单多次提交,监听滚动事件。

//节流
function throttle(fn,delay){
    let valid = true
    return function() {
       if(!valid){
           //休息时间 暂不接客
           return false 
       }
       // 工作时间,执行函数并且在间隔期内把状态位设为无效
        valid = false
        setTimeout(() => {
            fn()
            valid = true;
        }, delay)
    }
}
//目标函数
function handle(){
  console.log(Math.random())
}
//监听节流
window.onscroll = throttle(handle,1000)

以上代码的效果就是,当滚动条一直处于滚动状态时,每隔一秒输出一个随机数。

总结:(当持续触发时)防抖让事件只在最后一次发生。节流让事件每隔一段时间触发一次


然后看看vue的官方文档里面提到的使用lodash库来实现防抖的。vue在watch时使用防抖

<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // 如果 `question` 发生改变,这个函数就会运行
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.debouncedGetAnswer()
    }
  },
  created: function () {
    // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
    // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
    // 请参考:https://lodash.com/docs#debounce
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },
  methods: {
    getAnswer: function () {
      //do something...
    }
  }
})
</script>

可以发现有了lodash这个JavaScript库之后,要写节流可防抖是非常方便的。
然后看看lodash里面关于防抖debounce节流throttle的相关介绍吧。

防抖debounce

_.debounce(func, [wait=0], [options={}])

debounce的参数
func (Function): 要防抖动的函数。
[wait=0] (number): 需要延迟的毫秒数。
[options={}] (Object): 选项对象。
[options.leading=false] (boolean): 指定在延迟开始前调用。
[options.maxWait] (number): 设置 func 允许被延迟的最大值。
[options.trailing=true] (boolean): 指定在延迟结束后调用。

// 避免窗口在变动时出现昂贵的计算开销。
jQuery(window).on('resize', _.debounce(calculateLayout, 150));

节流throttle

_.throttle(func, [wait=0], [options={}])

throttle的参数
func (Function): 要节流的函数。
[wait=0] (number): 需要节流的毫秒。
[options={}] (Object): 选项对象。
[options.leading=true] (boolean): 指定调用在节流开始前。
[options.trailing=true] (boolean): 指定调用在节流结束后。

// 避免在滚动时过分的更新定位
jQuery(window).on('scroll', _.throttle(updatePosition, 100));

我大概看了一下lodash的官方文档,很丰富耶,感觉如果用这个js库的话可以省事又规范,找时间看一哈。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容