js 函数的防抖(debounce)与节流(throttle) 带 插件完整解析版 [helpers.js]
前言:
本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽。
函数防抖与节流是做什么的?下面进行通俗的讲解。
本文借鉴:https://www.cnblogs.com/cc-freiheit/p/10827372.html
大致原理:
函数防抖: 函数防抖做一件事,这件事并不是立即去做,而是等到一段时间之后再去做。如果这段时间内有一个东西再次触发了,那么就再等一次时间。
函数节流: 函数节流是指在某一段时间,去执行意见事,但是他不会重新停止计时,他只能保证在某一段时间内运行一次。
函数节流与函数防抖的区别:
函数节流是固定一段时间运行,会持续触发事件。函数防抖则是在一段事件内运行一次以后不会持续触发事件,要等一段时间才会再次触发。
准备工作:
<div class="text"
style="height:150px; line-height:150px; text-align:center; color:#000000; background-color:rgb(212, 233, 163); font-size:80px;">
</div>
<script>
var text = document.querySelector('.text');
var num = 1;
function count() {
text.innerHTML = num++;
};
text.onmousemove = debounce(count, 1000);
</script>
上面代码运行时,鼠标在绿色区域移动时,由于count函数的持续触发,会导致下图效果

为了避免频繁触发,我们可以使用函数防抖和函数节流来限制频繁触发
函数防抖:
// 非立即执行版
<script>
function debounce(callback, time) {
var timer;
return function () {
var args = arguments;
var self = this;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
callback.apply(self, args);
}, time)
}
}
</script>
使用方法:
text.onmousemove = debounce(count, 1000);
非立即执行版的意思是触发事件后函数不会立即执行,而是在 time秒后执行,如果在 time 秒内又触发了事件,则会重新计算函数执行时间。(鼠标移出元素时还会触发最后一次)效果如下:

// 立即执行版
<script>
function debounce(callback, time) {
var timer;
return function () {
var args = arguments;
var self = this;
if (timer) {
clearTimeout(timer);
}
var callNow = !timer;
timer = setTimeout(function () {
timer = null;
}, time);
if (callNow) {
callback.apply(self, args);
}
}
}
</script>
立即执行版的意思是触发事件后函数会立即执行,然后 time 秒内不触发事件才能继续执行函数的效果。用法同上。(鼠标移出元素时,视time的间隔而确定是否触发最后一次)效果如下

函数节流:
<script>
// 定时器版
function throttle(callback, time) {
var timer;
return function () {
if(timer) {
return;
}
var args = arguments;
var self = this;
timer = setTimeout(function () {
callback.apply(self, args);
timer = null;
},time);
}
}
</script>
使用方法:
text.onmousemove = throttle(count, 1000);
效果如下

定时器执行版的意思是在持续触发事件的过程中,函数不会立即执行,并且每 1s 执行一次。(在移出触发事件后,函数还会再执行一次。)
<script>
// 时间戳版
function throttle(callback, time) {
var t = 0; // 定义一个时间戳
return function () {
var nowDate = Date.now(); //获取当前时间戳
console.log(nowDate)
var args = arguments;
var self = this;
if (Date.now() - t >= time) {
callback.apply(self, args);
t = Date.now();
}
}
}
</script>
使用方法:
text.onmousemove = throttle(count, 1000);
效果如下

时间戳版的意思是在持续触发事件的过程中,函数会立即执行,并且每 1s 执行一次。(在移出触发事件后,函数还会再执行一次。)
函数防抖合并插件版
// helpers.js
/**
* 函数防抖
* @param {Function} callback 回调函数
* @param {Number} time 延迟的时间
* @param {Boolean} immediate 是否立即执行
*/
this.myPlugin.debounce = function (callback, time, immediate) {
// 设置默认值(如果用户未传参数immediate的情况下)
if (immediate === undefined) {
immediate = true;
}
var timer; // 定义一个定时器
if (immediate) {
return function () {
clearTimeout(timer); // 直接清楚之前的定时器
var self = this; // 保存this的值
var args = arguments; // 利用闭包保存参数数组
var callNow = !timer; // 取反
timer = setTimeout(function () {
timer = null; // 清空定时器
}, time)
if (callNow) {
callback.apply(self, args); //调用apply进行参数的传入
}
}
} else {
return function () {
clearTimeout(timer); // 直接清除之前的定时器
var self = this; // 保存this的值
var args = arguments; // 利用闭包保存参数数组
timer = setTimeout(function () {
callback.apply(self, args); // 调用apply进行参数的传入
}, time);
}
}
}
函数节流合并插件版
// helpers.js
/**
* 函数节流
* @param {Function} callback 回调函数
* @param {Number} time 延迟的时间
* @param {Boolean} immediate 是否立即执行
*/
this.myPlugin.throttle = function (callback, time, immediate) {
if (immediate === undefined) {// 设置默认值(如果用户未传参数immediate的情况下)
immediate = true;
}
if (immediate) {
var t; // 定义一个时间戳,默认为null
return function () {
var self = this; // 保存this的值
var args = arguments; // 利用闭包保存参数数组
// 只要时间没有值就可以执行函数 或 距离上次执行的时间已超过规定的值
// 当前时间戳 - 之前的时间戳 ≥ 传入的时间
if (!t || Date.now() - t >= time) {
callback.apply(self, args);
t = Date.now();
}
}
} else {
var timer;
return function () {
if (timer) {
return;// 如果有计时器的情况下直接返回
}
var self = this; // 保存this的值
var args = arguments; // 利用闭包保存参数数组
timer = setTimeout(function () {
callback.apply(self, args); // 调用apply进行参数的传入
timer = null; // 函数节流要清空定时器,如果这里不清空,他会发现上面一直有定时器(return那里),就不会再次运行了
}, time)
}
}
}
插件这样使用:
<!--插件要考虑通用性,易用性,尽量不要与其他功能冲突,防止污染太多的window上的全局变量,因此我这里使用多个js文件只污染一个全局变量的方式!在helpers.js中添加如下代码
if (!this.myPlugin) {
this.myPlugin = {};
}
-->
<script src="../../plugin/helpers.js"></script> <!--引入插件-->
<script>
var handle = myPlugin.debounce(function (width) { // 调用插件
console.log(width); // 打印浏览器视口宽度
}, 1000); // 每隔1000毫秒打印一次
window.onresize = function () {
handle(document.documentElement.clientWidth); // 浏览器窗口改变时触发
}
</script>
结语
怀着瑟瑟发抖的心情发了第一篇知识博客,有哪儿写错的请各位大牛指出。
好想进入小白之列,与大牛肩并脚。
js 函数的防抖(debounce)与节流(throttle) 带 插件完整解析版 [helpers.js]的更多相关文章
- js 函数对象的继承 inherit 带 插件完整解析版[helpers.js]
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS的对象继承方法 需求分析: 1. ...
- js 函数的防抖(debounce)与节流(throttle)
原文:函数防抖和节流: 序言: 我们在平时开发的时候,会有很多场景会频繁触发事件,比如说搜索框实时发请求,onmousemove, resize, onscroll等等,有些时候,我们并不能或者不想频 ...
- 防抖debounce和节流throttle
大纲 一.出现缘由 二.什么是防抖debounce和节流throttle 三.应用场景 3.1防抖 3.2节流 一.出现缘由 前端开发中,有一部分用户行为会频繁触发事件,而对于DOM操作,资源加载等耗 ...
- js 实现对象的混合与克隆效果,带完整版解析代码[helpers.js]
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS写淘宝无缝轮播图效果 对象混合 ...
- Java版的防抖(debounce)和节流(throttle)
概念 防抖(debounce) 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时. 防抖,即如果短时间内大量触发同一事件,都会 ...
- js 防抖 debounce 与 节流 throttle
debounce(防抖) 与 throttle(节流) 主要是用于用户交互处理过程中的性能优化.都是为了避免在短时间内重复触发(比如scrollTop等导致的回流.http请求等)导致的资源浪费问题. ...
- 防抖(Debounce)与节流( throttle)区别
http://www.cnblogs.com/ShadowLoki/p/3712048.html http://blog.csdn.net/tina_ttl/article/details/51830 ...
- JavaScript 防抖(debounce)和节流(throttle)
防抖函数 触发高频事件后,n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间 /** * * @param {*} fn :callback function * @param {* ...
- C#.Net下的防抖-Debounce和节流阀-Throttle功能实现
C#下的防抖-Debounce.节流阀-Throttle功能实现 防抖-Debounce 连续的多次调用,只有在调用停止之后的一段时间内不再调用,然后才执行一次处理过程. 节流阀-Throttle 连 ...
随机推荐
- Linux学习66 运维安全-通信加密和解密技术入门
一.Linux Service and Security 1.OpenSSL(ssl/tls)协议 2.OpenSSH(ssh)协议 3.bind(dns) 4.web(http):httpd(apa ...
- K:leetcode 5381.查询带键的排列 这题简单,但我还能优化。精益求精,才是算法的乐趣所在!
前言: 本题来自leetcode第184场周赛的第二小题.以前参加过周赛,觉得很有趣.苦于最近一段时间比较忙就没坚持参加了(实际上是借口来着....),由于昨晚思考一些事情,导致睡不着,所以起得有点早 ...
- 安装部署Tomcat服务器
安装部署Tomcat服务器 案例1:安装部署Tomcat服务器 案例2:使用Tomcat部署虚拟主机 案例3:使用Varnish加速Web 1案例1:安装部署Tom ...
- 安装一个KVM服务器
安装一个KVM服务器 案例1:安装一个KVM服务器 案例2:KVM平台构建及 ...
- css | js 实现扩展卡片小demo
1.代码如下 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- docker 相关操作
docker-compose down //关闭所有容器 docker-compose up //开启所有容器 docker-compose restart //重启所有容器 单独更新某个容器时用脚本 ...
- Java第三十二天,IO操作(续集),读写缓冲区的使用
缓冲区出现原因: Java对IO的读写都是经过中间途经--JVM虚拟机进行管理的,JVM调用OS操作系统继续完成IO操作.如此一来,整个过程耗费了不小的资源,为了尽量减少这样重复的周期性操作,出现了缓 ...
- nghttp2 交叉编译
touch run.sh chmod 755 run.sh mkdir build cd build ../run.sh run.sh #!/bin/bash #cd build ../configu ...
- Spring3.2 中 Bean 定义之基于 XML 配置方式的源码解析
Spring3.2 中 Bean 定义之基于 XML 配置方式的源码解析 本文简要介绍了基于 Spring 的 web project 的启动流程,详细分析了 Spring 框架将开发人员基于 XML ...
- Starlims Client Request Portal 客户申请门户
用户可以直接在starlims对外的"客户申请门户"上发起检验申请,并追踪检验进度等. 工作流程图示如下: