前言

事件的触发权很多时候属于用户,可能会出现下列问题:

  • 向后台发送数据,用户频繁触发,对服务器造成压力;
  • 一些浏览器事件,如window.onresize,window.mousemove等,触发的频率会非常高,会造成浏览器性能问题。

如果碰到这些问题,那就需要用到函数节流与防抖了。

一、函数节流(throttle)

函数节流:一个函数执行一次后,只有大于设定的执行周期后才会执行第二次。

有个需要频繁触发函数,处于优化性能角度,在规定时间内,只让函数触发的第一次生效,后面不生效。

1.如何实现

其原理是用时间戳来判断是否已到回调执行时间,记录上次执行的时间戳,然后每次触发scroll事件执行回调,回调中判断当前时间戳距离上次执行的时间戳的间隔是否已经达到规定时间段,如果是,则执行,并更新上次执行的时间戳,如此循环;

 html,
body {
height: 500%; // 让其出现滚动条
}
function throttle(fn,delay){
// 记录上一次函数触发时间
var lastTime = 0;
return function(){
// 记录当前函数触发时间
var nowTime = Date.now();
if(nowTime - lastTime > delay){
// 修正this指向
fn.call(this);
// 同步时间
lastTime = nowTime;
}
}
} document.onscroll = throttle(function() { console.log('scroll事件被触发了' + Date.now()) }, 200)
function throttle(fn, interval = 300) {
let canRun = true;
return function () {
if (!canRun) return;
canRun = false;
setTimeout(() => {
fn.apply(this, arguments);
canRun = true;
}, interval);
};
}

运用闭包的特性 -- 可以使变量 lastTime 长期保存着内存中

2.函数节流应用场景

需要间隔一定时间触发回调来控制函数调用频率:

  • DOM 元素的拖拽功能实现(mousemove)
  • 搜索联想(keyup)
  • 计算鼠标移动的距离(mousemove)
  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
  • 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次

二、函数防抖(debounce)

防抖函数:一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效。

1.如何实现

原理:
第一次调用函数时,创建一个定时器,在指定的时间间隔后执行代码。第二次调用函数时,会清除前一个定时器并设置另一个。如果前一个定时器尚未执行,就将其替换成一个新的定时器,然后延迟一定时间再执行。

<button id='btn'>按钮</button>
<script>
function debounce(fn,delay){
// 记录上一次的演示器
var timer = null;
return function(){
// 清除上一次延时器
clearTimeout(timer)
timer = setTimeout(function(){
fn.call(this);
},delay)
}
}
document.getElementById('btn').onclick = debounce(function() {
console.log('点击事件被触发' + Date.now())
}, 1000)
</script>

运用闭包的特性 -- 可以使变量 timer 长期保存着内存中

2.函数防抖应用场景

对于连续的事件响应我们只需要执行一次回调:

  • 每次 resize/scroll 触发统计事件
  • 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)

三、总结

函数节流 和 函数防抖 的核心就是限制某一个方法频繁触发,巧妙运用 setTimeout 来存放待执行的函数,这样可以很方便的利用  clearTimeout 在合适的时机来清除待执行的函数。

使用 函数节流 和 函数防抖 的目的,是为了节约计算机资源。

随笔参考
  https://www.jianshu.com/p/4e009e538503
  https://juejin.im/entry/58c0379e44d9040068dc952f
感谢博主分享!

JS 函数节流与防抖的更多相关文章

  1. js 函数节流和防抖

    js 函数节流和防抖 throttle 节流 事件触发到结束后只执行一次. 应用场景 触发mousemove事件的时候, 如鼠标移动. 触发keyup事件的情况, 如搜索. 触发scroll事件的时候 ...

  2. JS函数节流和防抖

    看JS高级程序设计时,了解到一个概念--函数节流,是为了防止在高频率触发某些事件导致浏览器崩溃.最近又了解到另一个概念,防抖,感觉和函数节流很像,也查看了很多篇博文,算是理解了. 区别: 函数节流:频 ...

  3. js函数节流和防抖的理解与实现

    一:函数防抖1.理解:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间2.思路:每次触发事件时都取消之前的延时调用方法 3.实现: function debounce ...

  4. 也谈js函数节流

    1.什么是js函数节流 其本质就是不让某些代码(函数)在没有间断的情况下连续重复执行,目的就是让执行函数的请求停止了一段时间后才执行. 2.函数节流运用的场景 窗口大小的改变(resize事件),滚动 ...

  5. JS在项目中用到的AOP, 以及函数节流, 防抖, 事件总线

    1. 项目中在绑定事件的时候总想在触发前,或者触发后做一些统一的判断或逻辑,在c#后端代码里,可以用Attribute, filter等标签特性实现AOP的效果,可是js中没有这种用法,归根到本质还是 ...

  6. JS函数节流和函数防抖问题分析

    问题1:如果实现了dom拖拽功能,但是在绑定拖拽事件的时候发现每当元素稍微移动一点便触发了大量的回调函数,导致浏览器直接卡死,这个时候怎么办? 问题2:如果给一个按钮绑定了表单提交的post事件,但是 ...

  7. js函数节流和函数防抖

    概念解释 函数节流: 频繁触发,但只在特定的时间内才执行一次代码 函数防抖: 频繁触发,但只在特定的时间内没有触发执行条件才执行一次代码 函数节流 函数节流应用的实际场景,多数在监听页面元素滚动事件的 ...

  8. JS定时器实现函数节流和防抖 -简单实现对比 -适用地方

    如题 (总结要点) 防止重复点击! 最近项目中遇见这个"函数抖动"的问题!快速点击前端xx按钮,造成数据多次加载进页面里,正常只显示10条数据,结果显示了20条数据,异常! 出现原 ...

  9. Underscore.js 函数节流简单测试

    函数节流在日常的DOM界面数据交互中有比较大的作用,可以减少服务器的请求,同时减少客户端的内存影响 Underscore.js  本省就包含了函数节流的处理函数 _.throttle 和 _.debo ...

随机推荐

  1. iOS 字典实现原理

    在目前的开发中,NSDictionary是经常被使用,不过很少人会研究字典NSDictionary底层的实现,下面我们来一起看一下NSDictionary的实现原理. 一.字典原理 字典通过使用- ( ...

  2. 杭电ACM2016--数据的交换输出

    数据的交换输出 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  3. C# string数组转int数组(转载)

    C# string数组转int数组   用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 //字符串数组(源数组) string[] sNums = new[] {"1 ...

  4. js三部曲---预编译

    函数内:1,创建AO对象//Activation Object 2,找函数内形参和变量声明,将其作为AO对象的属性名,值为undefined. 3,实参赋到AO对象 形参名里 4,在函数体里找函数声明 ...

  5. Oracle day04 DML_事务_序列_视图_数据类型_DDL

    DMLinsert关键字作用:往表中插入一条(多条)数据 语法1:元祖值式的插入语法1: insert into tablename(column1,column2,...,columnN) valu ...

  6. JS之This的用法

    This的用法 This作为JavaScript中的关键字,在函数中具有四种用法. 一.直接在函数中使用,谁调用这个函数,this就指向谁 例如: var n = "指我"; fu ...

  7. node处理表单文件,获取formdata的数据

    参考文章:https://blog.csdn.net/a895458278/article/details/48055143# 应用: formidable使用: 原生的node.js在处理客户端以P ...

  8. input 图片上传,第二次上传同一张图片失效

    <input type="file" onchange="angular.element(this).scope().addPhoto(this,event)&qu ...

  9. 【20190228】JavaScript-获取子元素

    在写JavaScript的时候发现了一个获取子节点的坑,如以下的html结构 <div id="parent"> <div>1</div> &l ...

  10. clCreateBuffer和clCreateBuufer + clEnqueueWriteBuffer

    有两种方式实现从主机到CL设备的数据传递, 第一种: cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DA ...