翼度科技»论坛 编程开发 JavaScript 查看内容

防抖和节流及多种实现方式

9

主题

9

帖子

27

积分

新手上路

Rank: 1

积分
27
当用户在网页中进行操作时,如点击、滚动、输入等,往往会频繁地触发事件。如果每个事件都立即执行相应的函数,可能会导致性能问题和用户体验不佳,因为这些函数可能需要执行复杂的操作,如计算、网络请求等。
为了优化这种情况,我们可以使用防抖和节流来限制函数的调用次数,从而提高性能和用户体验。
 

    防抖
  防抖是指在一定的时间间隔内,将多次触发的事件合并成一次执行。  
防抖的实现思路是:每次事件被触发时,设置一个计时器,在指定的时间间隔内,如果该事件被再次触发,则清除计时器并重新开始计时,直到指定的时间间隔内没有事件触发为止,然后调用函数。
 
防抖可以用于处理一些频繁触发的事件,如窗口大小改变、输入框输入等。以下是一个简单的防抖函数实现:
  1. function debounce(fn, delay) {
  2.   let timer;
  3.   return function() {
  4.     const context = this;
  5.     const args = arguments;
  6.     clearTimeout(timer);
  7.     timer = setTimeout(function() {
  8.       fn.apply(context, args);
  9.     }, delay);
  10.   };
  11. }
复制代码
 
这个函数接收两个参数: fn  是要防抖的函数, delay  是防抖时间间隔。返回一个新的函数,在防抖时间间隔内,重复调用这个新函数不会立即触发原函数,只有等时间间隔过去之后才会触发。
 


    节流
  节流是指在一定的时间间隔内,函数只被调用一次。如果在这个时间间隔内触发了多次事件,只有第一次会调用函数,其余的会被忽略。  
节流的实现思路是:每次事件被触发时,如果函数没有在指定的时间间隔内被调用过,则调用函数并设置一个计时器,在指定的时间间隔内不再触发事件。如果在指定的时间间隔内再次触发了事件,则不调用函数,直到指定的时间间隔过去,重新开始调用函数。
 
节流可以用于处理一些频繁触发的事件,如页面滚动、鼠标移动等。以下是一个简单的节流函数实现:
  1. function throttle(fn, delay) {
  2.   let timer;
  3.   return function() {
  4.     const context = this;
  5.     const args = arguments;
  6.     if (!timer) {
  7.       timer = setTimeout(function() {
  8.         fn.apply(context, args);
  9.         timer = null;
  10.       }, delay);
  11.     }
  12.   };
  13. }
复制代码
这个函数接收两个参数: fn  是要节流的函数, delay  是节流时间间隔。返回一个新的函数,在指定的时间间隔内,只能调用一次原函数。
 
 
防抖和节流的实现方式可以有多种,具体实现应该根据实际场景进行调整。下面介绍一些常见的实现方式。
 

    立即执行版和非立即执行版
防抖和节流的实现中,可以根据需求选择立即执行版或非立即执行版。
  立即执行版是指在每次触发事件时,立即执行一次函数,然后在指定的时间间隔内不再执行。这种方式适合处理一些需要立即响应的事件,如按钮点击等。  
 
以下是立即执行版的防抖函数实现:
  1. function debounce(fn, delay, immediate) {
  2.   let timer;
  3.   return function() {
  4.     const context = this;
  5.     const args = arguments;
  6.     if (immediate && !timer) {
  7.       fn.apply(context, args);
  8.     }
  9.     clearTimeout(timer);
  10.     timer = setTimeout(function() {
  11.       if (!immediate) {
  12.         fn.apply(context, args);
  13.       }
  14.       timer = null;
  15.     }, delay);
  16.   };
  17. }
复制代码
 
这个函数增加了一个参数 immediate ,用来指定是否立即执行函数。如果设置为 true ,则在触发事件时立即执行函数;否则等待指定的时间间隔后再执行。
 
 
  非立即执行版是指在事件停止触发指定时间后才执行一次函数。这种方式适合处理一些连续触发的事件,如输入框输入等。  
以下是非立即执行版的防抖函数实现:
  1. function debounce(fn, delay, immediate) {
  2.   let timer;
  3.   return function() {
  4.     const context = this;
  5.     const args = arguments;
  6.     if (timer) {
  7.       clearTimeout(timer);
  8.     }
  9.     if (immediate && !timer) {
  10.       fn.apply(context, args);
  11.     }
  12.     timer = setTimeout(function() {
  13.       if (!immediate) {
  14.         fn.apply(context, args);
  15.       }
  16.       timer = null;
  17.     }, delay);
  18.   };
  19. }
复制代码
这个函数与立即执行版的实现相似,区别在于多了一个 if (timer) { clearTimeout(timer); } 判断。如果计时器已经存在,则在重新设置计时器之前先清除之前的计时器。
 

    时间戳版和定时器版
防抖和节流的实现中,可以根据需求选择时间戳版或定时器版。
  时间戳版是指在事件触发后,记录下当前的时间戳,并在下次事件触发时再次记录时间戳。在指定的时间间隔内,如果事件再次触发,则更新时间戳。如果时间戳与当前时间的差值超过了指定的时间间隔,则执行函数。这种方式适合处理一些需要立即响应的事件,如按钮点击等。  
 
以下是时间戳版的节流函数实现:
  1. function throttle(fn, delay) {
  2.   let last = 0;
  3.   return function() {
  4.     const context = this;
  5.     const args = arguments;
  6.     const now = +new Date();
  7.     if (now - last > delay) {
  8.       fn.apply(context, args);
  9.       last = now;
  10.     }
  11.   };
复制代码
这个函数中, last  记录上次执行函数的时间戳,每次事件触发时,计算当前时间戳与上次执行函数的时间戳的差值,如果超过指定的时间间隔,则执行函数并更新 last 。
 
 

  定时器版是指在事件触发后,设置一个定时器,在指定的时间间隔内不再触发事件。如果在指定的时间间隔内再次触发了事件,则不执行函数,直到定时器到期后再次执行函数。这种方式适合处理一些连续触发的事件,如页面滚动、鼠标移动等。  
 
以下是定时器版的节流函数实现:
  1. function throttle(fn, delay) {
  2.   let timer;
  3.   return function() {
  4.     const context = this;
  5.     const args = arguments;
  6.     if (!timer) {
  7.       timer = setTimeout(function() {
  8.         fn.apply(context, args);
  9.         timer = null;
  10.       }, delay);
  11.     }
  12.   };
  13. }
复制代码
这个函数与之前介绍的非立即执行版的防抖函数实现类似,区别在于将 setTimeout 的时间间隔设置为指定的时间间隔,而不是事件触发后的延迟时间。

  防抖和节流的主要区别在于它们限制函数调用的方式不同。防抖是指在指定的时间间隔内将多次触发的事件合并成一次执行,而节流是指在指定的时间间隔内,函数只被调用一次。同时,防抖和节流也有一些缺点,比如可能会导致事件响应延迟或事件被忽略等问题。因此,在实际使用中,需要根据场景进行权衡和选择。  
 

来源:https://www.cnblogs.com/ronaldo9ph/p/17348583.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具