函数防抖知识要点

函数防抖 debounce

JavaScript 中的函数大多数情况下都是由用户主动调用触发的,比如说点击、拖拽、改变浏览器尺寸、提交表单等。除非是函数本身的实现不合理,否则一般不会遇到跟性能相关的问题。

但是在一些少数情况下,函数的触发不是由用户直接控制的。在这些场景下,函数有可能被非常频繁地调用,而造成性能问题:

  • mousemove 事件。如果要实现一个拖拽功能,需要一路监听 mousemove 事件,在回调中获取元素当前位置来进行样式改变。如果不加以控制,每移动一定像素而触发的回调数量非常惊人,回调中又伴随着 DOM 操作,继而引发浏览器的重排与重绘,性能差的浏览器可能就会直接假死。

  • window.onresize 事件。为 window 对象绑定了 resize 事件,当浏览器窗口大小被拖动而改变尺寸的时候,这个事件就会一直被触发。如果在 window.onresize 事件函数里又有一些跟 DOM 节点相关的操作,浏览器可能就会吃不消而造成卡顿现象。

  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)不能因为连续点击或快速按键连续发射多颗子弹。

  • 搜索联想(keyup事件)

  • 监听滚动(scroll事件)

解决这些情况的方案就可以使用函数防抖(debounce),其核心就是限制某一个方法的频繁触发。防止函数在极短的时间内反复调用,造成资源的浪费。

场景设想

场景1

考虑一下电梯关门的场景,现代的大部分电梯都可以通过红外,感知到是否有人进入。为了避免夹到人,同时为了等待后面的人,电梯关门的时间往往有一种规则:**始终保证电梯门在最后一个人进入后 3 秒以后关闭。**如果有人进入后,还没有等到 3 秒,又有人进来了,电梯门会以最后一次进入的时间为计时起点,重新等待3秒。

场景2

再考虑一个页面上的场景。页面上的某些事件触发频率非常高,比如滚动条滚动、窗口尺寸变化、鼠标移动等,如果我们需要注册这类事件,不得不考虑效率问题,又特别是事件处理中涉及到了大量的操作,比如:

window.onresize = function(){
   
    // 大量的 DOM 操作
}

当窗口尺寸发生哪怕一丢丢变化时,都会造成多次对处理函数的调用,这对网页性能的影响是极其巨大的。于是,我们可以考虑,每次窗口尺寸变化、滚动条滚动、鼠标移动时,不要立即执行相关操作,而是等一段时间,以窗口尺寸停止变化、滚动条不再滚动、鼠标不再移动为计时起点,一段时间后再去执行操作,就像电梯关门那样。

场景3

再考虑一个搜索的场景,当用户在一个文本框中输入文字(keydown 事件)时,需要将文字发送到服务器,并从服务器得到搜索结果。这样的话,用户直接输入搜索文字就可以了,不用再去点搜索按钮,可以提升用户体验:

img

可是如何来实现上面的场景呢?如果文本框的文字每次被改变(keydown 或者 keyup),都要把数据发送到服务器,得到搜索结果,想想看,当搜索 “google” 这样的单词,至少需要按 6 次按键,就这一个词就需要向服务器请求 6 次,并让服务器去搜索 6 次,但其实只需要最后一次的结果就可以了。如果考虑用户按错的情况,发送请求的次数更加恐怖,浪费了很多资源。

所以真正的搜索行为并不是每次输入都会触发的,只有当用户停止按键一段时间后才会触发。

推测代码

为了满足这种类型场景,可以设计需要满足以下功能:

  1. 调用该函数后,不立即做事,而是一段时间后去做事
  2. 如果在等待时间内调用了该函数,则重新开始计时

这样的功能,就叫做函数防抖,其实就是防止函数短时间内被调用多次。要完成该函数,需要给予两个条件:

  1. 告诉我一段时间后要做什么事(这里应该是一个 callback,即函数作为参数)
  2. 告诉我要等待多长时间

那思考一下,什么东西可以 “在某个时间后触发一次” ?延时型计时器 setTimeout!没错,所以……代码可能?可以写成:

// 省略了标签 <input type="text" id='txt'> 别问为啥,就是想。
txt.onkeyup = function () {
   
  se
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: JavaScript 函数防抖(debounce)是一种技术,可以防止函数在短时间内多次触发。 当函数被触发时,防抖函数会延迟执行函数,并且如果在延迟期间内再次触发函数,则会重新计算延迟时间。这样可以避免函数在短时间内多次触发,从而节省资源。 举个例子,假设你有一个函数,用于搜索用户输入的内容。如果每次用户输入都立即触发函数,会导致函数频繁触发,浪费资源。使用防抖函数,可以在用户输入后延迟一段时间才触发函数,从而节省资源。 下面是一个简单的防抖函数的例子: ``` function debounce(fn, delay) { let timer = null; return function () { const context = this; const args = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.apply(context, args); }, delay); } } ``` 上面的防抖函数接受两个参数:`fn` 是要进行防抖函数,`delay` 是延迟时间(单位为毫秒)。防抖函数返回一个新函数,在新函数中设置了延迟执行的逻辑。 使用防抖函数的方法如下: ``` const debouncedFunction = debounce(function () { // 在这里 ### 回答2: JavaScript 函数防抖是一种常用的优化技术,旨在减少函数的调用频率。 当一个函数被频繁触发时,防抖机制会在一定的延迟时间内,只执行最后一次触发的函数调用。这样可以避免函数被频繁执行,提高性能和用户体验。 实现函数防抖有两种方式:立即执行和延迟执行。 立即执行的函数防抖,意味着只有当函数被最后一次调用时,才会立即执行函数。延迟执行的函数防抖,意味着只有当函数在一定时间内没有被再次调用时,才会执行函数。 通过使用定时器和闭包,可以实现函数防抖的功能。当函数被触发时,先清除之前设置的定时器,然后重新设置一个延迟执行的定时器。如果在延迟时间内再次触发函数,就会清除之前设置的定时器,重新设置一个新的延迟执行的定时器。只有当延迟时间内没有再次触发函数,定时器才会执行函数函数防抖在多种场景中都有应用。比如在用户输入搜索框时,可以使用函数防抖来减少发送搜索请求的频率;在窗口大小改变时,可以使用函数防抖来优化页面重绘的性能。 总之,JavaScript 函数防抖是一种常用的优化技术,通过减少函数的调用频率来提高性能和用户体验。在实现上,可以通过定时器和闭包来实现函数防抖的功能。 ### 回答3: JavaScript函数防抖是一种提高性能和优化用户体验的技术。它所解决的问题是在一段时间内频繁触发某个函数时,只执行最后一次触发的函数调用。 实现函数防抖的方法是利用定时器。当触发事件时,会开始一个定时器,如果在指定的时间间隔内再次触发了该事件,定时器就会被清除并重新开始计时。这样,只有在最后一次触发事件后的等待时间内没有再次触发,才会执行相应的函数调用。 函数防抖在实际应用中有很多场景。比如,在用户输入搜索框时,可以利用函数防抖来减少发送请求的次数,只在用户停止输入一段时间后才发起实际的搜索请求。又如,在窗口大小调整时,可以利用函数防抖来优化响应式布局,只在窗口停止调整一段时间后才重新计算样式。 以下是一个简单的实现函数防抖的示例代码: ```javascript function debounce(func, delay) { let timerId; return function() { const context = this; const args = arguments; clearTimeout(timerId); timerId = setTimeout(function() { func.apply(context, args); }, delay); }; } // 创建一个防抖函数 const debouncedFunc = debounce(function() { console.log('Function debounced'); }, 300); // 触发函数 debouncedFunc(); // 不会执行 debouncedFunc(); // 不会执行 debouncedFunc(); // 不会执行 // 等待300毫秒后,只执行一次 ``` 以上示例代码中,`debounce`函数接受一个函数和一个延迟时间参数,返回一个新函数,实现了函数防抖的逻辑。在创建防抖函数后,多次调用这个函数,只有停止调用一段时间后才会执行实际的函数逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值