在前端开发的过程中,我们经常会需要绑定一些持续触发的事件,如 resize、scroll、mousemove 等等,但有些时候我们并不希望在事件持续触发的过程中那么频繁地去执行函数。

通常这种情况下我们怎么去解决的呢?一般来讲,防抖和节流是比较好的解决方案。

让我们先来看看在事件持续触发的过程中频繁执行函数是怎样的一种情况。

html 文件中代码如下

let num = 1;

let content = document.getElementById('content');

function count() {

content.innerHTML = num++;

};

content.onmousemove = count;

在上述代码中,div 元素绑定了 mousemove 事件,当鼠标在 div(灰色)区域中移动的时候会持续地去触发该事件导致频繁执行函数。效果如下

可以看到,在没有通过其它操作的情况下,函数被频繁地执行导致页面上数据变化特别快。所以,接下来让我们来看看防抖和节流是如何去解决这个问题的。

防抖(debounce)

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

防抖函数分为非立即执行版和立即执行版。

非立即执行版:

function debounce(func, wait) {

let timeout;

return function () {

let context = this;

let args = arguments;

if (timeout) clearTimeout(timeout);

timeout = setTimeout(() => {

func.apply(context, args)

}, wait);

}

}

非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

我们依旧使用上述绑定 mousemove 事件的例子,通过上面的防抖函数,我们可以这么使用

content.onmousemove = debounce(count,1000);

效果如下

可以看到,在触发事件后函数 1 秒后才执行,而如果我在触发事件后的 1 秒内又触发了事件,则会重新计算函数执行时间。

上述防抖函数的代码还需要注意的是 this 和 参数的传递

let context = this;

let args = arguments;

防抖函数的代码使用这两行代码来获取 this 和 参数,是为了让 debounce 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。

立即执行版:

function debounce(func,wait) {

let timeout;

return function () {

let context = this;

let args = arguments;

if (timeout) clearTimeout(timeout);

let callNow = !timeout;

timeout = setTimeout(() => {

timeout = null;

}, wait)

if (callNow) func.apply(context, args)

}

}

立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。

使用方法同上,效果如下

在开发过程中,我们需要根据不同的场景来决定我们需要使用哪一个版本的防抖函数,一般来讲上述的防抖函数都能满足大部分的场景需求。但我们也可以将非立即执行版和立即执行版的防抖函数结合起来,实现最终的双剑合璧版的防抖函数。

双剑合璧版:

/**

* @desc 函数防抖

* @param func 函数

* @param wait 延迟执行毫秒数

* @param immediate true 表立即执行,false 表非立即执行

*/

function debounce(func,wait,immediate) {

let timeout;

return function () {

let context = this;

let args = arguments;

if (timeout) clearTimeout(timeout);

if (immediate) {

var callNow = !timeout;

timeout = setTimeout(() => {

timeout = null;

}, wait)

if (callNow) func.apply(context, args)

}

else {

timeout = setTimeout(function(){

func.apply(context, args)

}, wait);

}

}

}

节流(throttle)

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。

对于节流,一般有两种方式可以实现,分别是时间戳版和定时器版。

时间戳版:

function throttle(func, wait) {

let previous = 0;

return function() {

let now = Date.now();

let context = this;

let args = arguments;

if (now - previous > wait) {

func.apply(context, args);

previous = now;

}

}

}

使用方式如下

content.onmousemove = throttle(count,1000);

效果如下

可以看到,在持续触发事件的过程中,函数会立即执行,并且每 1s 执行一次。

定时器版:

function throttle(func, wait) {

let timeout;

return function() {

let context = this;

let args = arguments;

if (!timeout) {

timeout = setTimeout(() => {

timeout = null;

func.apply(context, args)

}, wait)

}

}

}

使用方式同上,效果如下

可以看到,在持续触发事件的过程中,函数不会立即执行,并且每 1s 执行一次,在停止触发事件后,函数还会再执行一次。

我们应该可以很容易的发现,其实时间戳版和定时器版的节流函数的区别就是,时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。

同样地,我们也可以将时间戳版和定时器版的节流函数结合起来,实现双剑合璧版的节流函数。

双剑合璧版:

/**

* @desc 函数节流

* @param func 函数

* @param wait 延迟执行毫秒数

* @param type 1 表时间戳版,2 表定时器版

*/

function throttle(func, wait ,type) {

if(type===1){

let previous = 0;

}else if(type===2){

let timeout;

}

return function() {

let context = this;

let args = arguments;

if(type===1){

let now = Date.now();

if (now - previous > wait) {

func.apply(context, args);

previous = now;

}

}else if(type===2){

if (!timeout) {

timeout = setTimeout(() => {

timeout = null;

func.apply(context, args)

}, wait)

}

}

}

}

参考文章:

防抖与节流方案_函数防抖和节流相关推荐

  1. 防抖与节流方案_如何理解js的防抖与节流

    很高兴回答你这个问题,希望可以给你讲述清楚! 我们先举个例子: 项目有个需求是输入框在输入的时候进行搜索,展示下拉数据,但是没必要输入一个字都进行搜索,所以想到了在输入结束200毫秒后再进行搜索,从而 ...

  2. 防抖与节流方案_前端ajax优化解决方案

    伴随着前端ajax的应用场景越来越多,那就免不了一个整合的ajax优化解决方案了,自己优化太麻烦?没事,有它帮你解决:hajax 与当下比较热门的请求库 axios 和原生的 fetch相比,haja ...

  3. 防抖与节流方案_关于图片懒加载的几种方案

    作者: 山月行 转发链接:https://mp.weixin.qq.com/s/rY1LbW95LR6AqF1Vcx_d1Q 懒加载,顾名思义,在当前网页,滑动页面到能看到图片的时候再加载图片 故问题 ...

  4. 虾扯蛋之函数防抖和节流

    背景     今天在coding的时候,做了一个搜索框,也正是这个搜索框,让我和后台小伙伴直接由铁磁变为塑料兄弟.那到底发生啥了呢?其实很简单,其实很无奈,就是我用王者的手速把他的接口访问崩了!    ...

  5. 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用

    函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 文章目录 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 1. 为什么要防抖节流 1.1 ...

  6. 防抖 节流_每日一题手写函数防抖与节流

    关注"前端学苑" ,坚持每天进步一点点 「~函数防抖与节流 ~」 每日一题,希望让爱学习.思考的前端技术伙伴在一起学习.复盘.成长. 基础知识要夯实,原理源码要深入,深度广度要扩展 ...

  7. resize函数_每日一题手写函数防抖与节流

    关注"前端学苑" ,坚持每天进步一点点 「~函数防抖与节流 ~」 每日一题,希望让爱学习.思考的前端技术伙伴在一起学习.复盘.成长. 基础知识要夯实,原理源码要深入,深度广度要扩展 ...

  8. timertask run函数未执行_函数的防抖和节流是个啥???

    内容来源:SegmentFault社区 作者:nero 整理编辑:SegmentFault 曾经面试时候被问到过这个,年少的我一脸无知... 后来工作中遇到了一个场景:输入名称的同时去服务器校验名称是 ...

  9. ege限制鼠标移动的函数_浅谈函数节流和函数防抖

    什么是函数节流和函数防抖?下面本篇文章就来给大家浅谈一下函数节流和函数防抖.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 前言 事件的触发权很多时候都属于用户,有些情况下会产生问题 ...

最新文章

  1. R语言操作excel文件的数据
  2. git常用命令(克隆、分支、tag标签、推送、日志查看,常用命令总结)、将本地代码第一次提交到远程git仓库、过滤掉不提交的内容
  3. 最不像地球的45个地方,你都见过几个?
  4. r语言mfrow全程_R语言中的色彩_LearningR - SegmentFault 思否
  5. ffmpeg: error while loading shared libraries: libavdevice.so.52
  6. python 清华镜像_Anaconda3清华镜像 V5.3.1 最新免费版
  7. three.js几何体的旋转,缩放,平移
  8. 9、Android---UI---Material Design
  9. MYSQL锁机制---MyISAM表锁
  10. 如何对PDF文件的文字图片编辑修改
  11. Tomcat+Servlet面试题都在这里
  12. 物理学 物体的运动力学分析之牛顿三定律 单摆的MATLAB运动仿真(一)
  13. matlab 图像锐化 梯度 原理,Matlab梯度法图像锐化
  14. 思科模拟器配置默认路由(下一跳使用端口)
  15. Android Studio基础-Activity生命周期与多个Activity跳转
  16. 你还在用乞丐版的深拷贝么
  17. 计算机键盘无法识别,键盘无法识别的解决妙招
  18. padavan做副路由,主路由是原厂固件,如何使用adguardHome过滤广告
  19. 字节辟谣被裁员工与 HR 互殴;苹果头显多个新功能曝光;谷歌希望 RISC-V 成为 T1 级 Android 架构|极客头条
  20. 想要申请PhD,真是路漫漫啊

热门文章

  1. DataLoader worker (pid 2287) is killed by signal: Killed. pytorch训练解决方法
  2. redis集群如何解决重启不了的问题
  3. 更新条目时出错。有关详细信息,请参见内部异常。
  4. python工作流程_讨论 - 廖雪峰的官方网站
  5. 哪些因素造成外贸网站没效果?
  6. 卸载程序_App Cleaner Pro for Mac v6.10.1 程序卸载 直装版
  7. 动词ing基本用法_哪些动词后面只能接动名词背诵口诀
  8. 数据结构:B树和B+树的插入、删除图文详解
  9. 面试题简答题——操作系统相关汇总
  10. Linux编程(2)_软件的安装和卸载