手写防抖(debounce)和节流(throttle)
目录
测试代码
防抖(debounce)
基本功能实现
添加参数及this指向功能
第一次立即执行功能
取消功能
节流(throttle)
基本功能实现
增加this执向
最后一次在禁止时间段内是否执行
添加取消按钮
定时器实现节流
测试代码
import debounce from './手写防抖.js';
import throttle from './手写节流.js';const inputEl = document.querySelector("input");
const cancelBtn = document.querySelector("#cancel");let onBody = function (event) {console.log('最新的内容为: ', event, this);
}// 防抖测试代码 ---------------
let debounceChange = debounce(onBody, 3000);
inputEl.oninput = debounceChange;cancelBtn.onclick = function () {debounceChange.cancel()
}// 节流测试代码 ---------------
let throttleChange = throttle(onBody, 3000, true);
inputEl.oninput = throttleChange;cancelBtn.onclick = function () {throttleChange.cancel()
}
防抖(debounce)
需求:使函数延迟X秒后执行,未执行前调用则重置延迟时间。
实现思路:每次触发清楚宏任务中的事件并重新添加定时器执行。
基本功能实现
function debounce1(fn, delay = 0) {let timer = null;// 参数验证try {if (typeof fn !== 'function') throw new Error('参数一不是一个函数!');if (typeof delay !== 'number' || delay < 0) throw new Error('参数二不是一个正数!');} catch (err) {console.log(err);}return function _debounce() {if (timer) clearTimeout(timer)timer = setTimeout(() => {fn()}, delay);}
}
添加参数及this指向功能
function debounce2(fn, delay = 0) {let timer = null;// 参数验证try {if (typeof fn !== 'function') throw new Error('参数一不是一个函数!');if (typeof delay !== 'number' || delay < 0) throw new Error('参数二不是一个正数!');} catch (err) {console.log(err);}// 这里的args是事件回调的参数,和定义方法时传递的不冲突return function _debounce(...args) {if (timer) clearTimeout(timer)timer = setTimeout(() => {fn.apply(this, args) //改变this指向并把onclick的event传递}, delay);}
}
第一次立即执行功能
function debounce3(fn, delay = 0, immediate = false) {let timer = null;let isInvoke = false// 参数验证try {if (typeof fn !== 'function') throw new Error('参数一不是一个函数!');if (typeof delay !== 'number' || delay < 0) throw new Error('参数二不是一个正数!');if (typeof immediate !== 'boolean') throw new Error('参数三未不是一个布尔值!');} catch (err) {console.log(err);}return function _debounce(...args) {if (timer) clearTimeout(timer)if (!isInvoke && immediate) {fn.apply(this, args) //改变this指向并把onclick的event传递isInvoke = true} else {timer = setTimeout(() => {fn.apply(this, args) //改变this指向并把onclick的event传递isInvoke = false}, delay);}}
}
取消功能
/*** * @param {节流方法} fn * @param {延迟时间} delay * @param {是否立即执行} immediate * @returns */
export default function debounce(fn, delay = 0, immediate = false) {let timer = null;let isInvoke = false// 参数验证try {if (typeof fn !== 'function') throw new Error('参数一不是一个函数!');if (typeof delay !== 'number' || delay < 0) throw new Error('参数二不是一个正数!');if (typeof immediate !== 'boolean') throw new Error('参数三未不是一个布尔值!');} catch (err) {console.log(err);}const _debounce = function (...args) {if (timer) clearTimeout(timer)if (!isInvoke && immediate) {fn.apply(this, args) //改变this指向并把onclick的event传递isInvoke = true} else {timer = setTimeout(() => {fn.apply(this, args) //改变this指向并把onclick的event传递isInvoke = false}, delay);}}// 添加取消函数_debounce.cancel = () => {if (timer) clearTimeout(timer)timer = nullisInvoke = false}return _debounce
}
节流(throttle)
需求:X秒内只能执行一次
实现思路:
对比调用时间及上次执行时间的差决定是否执行(时间戳)
每次执行设置定时器,X秒后才能再次执行当前函数。(定时器)
基本功能实现
function throttle1(fn, delay = 0) {let lastTime = 0// 参数验证try {if (typeof fn !== 'function') throw new Error('参数一不是一个函数!');if (typeof delay !== 'number' || delay < 0) throw new Error('参数二不是一个正数!');} catch (err) {console.log(err);}const _throttle = function () {// 当前时间let nowTime = new Date().getTime();// 设置间隔时间 - ( 当前时间 - 上一次执行时间 )const remainTime = delay - (nowTime - lastTime)if (remainTime <= 0) {fn()lastTime = nowTime}}return _throttle
}
增加this执向
function throttle2(fn, delay = 0) {let lastTime = 0// 参数验证try {if (typeof fn !== 'function') throw new Error('参数一不是一个函数!');if (typeof delay !== 'number' || delay < 0) throw new Error('参数二不是一个正数!');} catch (err) {console.log(err);}const _throttle = function (...args) {// 当前时间let nowTime = new Date().getTime();// 设置间隔时间 - ( 当前时间 - 上一次执行时间 )const remainTime = delay - (nowTime - lastTime)if (remainTime <= 0) {fn.apply(this, args)lastTime = nowTime}}return _throttle
}
最后一次在禁止时间段内是否执行
function throttle3(fn, delay = 0, trailing = false) {let lastTime = 0let timer = null// 参数验证try {if (typeof fn !== 'function') throw new Error('参数一不是一个函数!');if (typeof delay !== 'number' || delay < 0) throw new Error('参数二不是一个正数!');if (typeof trailing !== 'boolean') throw new Error('参数三不是一个布尔值!');} catch (err) {console.log(err);}const _throttle = function (...args) {// 当前时间let nowTime = new Date().getTime();// 设置间隔时间 - ( 当前时间 - 上一次执行时间 )const remainTime = delay - (nowTime - lastTime)if (remainTime <= 0) {fn.apply(this, args)lastTime = nowTimeclearTimeout(timer)} else {if (!trailing) returnif (timer) clearTimeout(timer);timer = setTimeout(() => {fn.apply(this, args)lastTime = nowTime}, remainTime);}}return _throttle
}
添加取消按钮
/*** * @param {节流函数} fn * @param {延迟时间} delay * @param {最后一次是否执行} trailing * @returns */
function throttle(fn, delay = 0, trailing = false) {let lastTime = 0let timer = null// 参数验证try {if (typeof fn !== 'function') throw new Error('参数一不是一个函数!');if (typeof delay !== 'number' || delay < 0) throw new Error('参数二不是一个正数!');if (typeof trailing !== 'boolean') throw new Error('参数三不是一个布尔值!');} catch (err) {console.log(err);}const _throttle = function (...args) {// 当前时间let nowTime = new Date().getTime();// 设置间隔时间 - ( 当前时间 - 上一次执行时间 )const remainTime = delay - (nowTime - lastTime)if (remainTime <= 0) {fn.apply(this, args)lastTime = nowTimeclearTimeout(timer)} else {if (!trailing) returnif (timer) clearTimeout(timer);timer = setTimeout(() => {fn.apply(this, args)lastTime = nowTime}, remainTime);}}_throttle.cancel = function () {if (timer) clearTimeout(timer);timer = nulllastTime = 0}return _throttle
}
定时器实现节流
/*** * @param {节流函数} fn * @param {延迟时间} delay * @param {最后一次是否执行} trailing * @returns */
function throttle(fn, delay = 0, trailing = false) {let isInvoke = falselet isLastInvoke = falselet timer = null// 参数验证try {if (typeof fn !== 'function') throw new Error('参数一不是一个函数!');if (typeof delay !== 'number' || delay < 0) throw new Error('参数二不是一个正数!');if (typeof trailing !== 'boolean') throw new Error('参数三不是一个布尔值!');} catch (err) {console.log(err);}const _throttle = function (...args) {let _this = thisfunction t() {timer = setTimeout(() => {if (isLastInvoke) {isLastInvoke = falsefn.apply(_this, args)t();} else {isInvoke = false}}, delay);}if (!isInvoke) {isInvoke = truefn.apply(this, args)t();} else {if (!trailing) returnisLastInvoke = true}}_throttle.cancel = function () {if (timer) clearTimeout(timer);timer = nullisInvoke = falseisLastInvoke = false }return _throttle
}
手写防抖(debounce)和节流(throttle)相关推荐
- 防抖debounce和节流throttle
大纲 一.出现缘由 二.什么是防抖debounce和节流throttle 三.应用场景 3.1防抖 3.2节流 一.出现缘由 前端开发中,有一部分用户行为会频繁触发事件,而对于DOM操作,资源加载等耗 ...
- 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用
函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 文章目录 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 1. 为什么要防抖节流 1.1 ...
- 函数防抖(debounce)和节流(throttle)以及lodash的debounce源码赏析
函数节流和去抖的出现场景,一般都伴随着客户端 DOM 的事件监听.比如scroll resize等事件,这些事件在某些场景触发非常频繁. 比如,实现一个原生的拖拽功能(不能用 H5 Drag& ...
- 探究防抖(debounce)和节流(throttle)
本文来自我的博客,欢迎大家去GitHub上star我的博客 本文从防抖和节流出发,分析它们的特性,并拓展一种特殊的节流方式requestAnimationFrame,最后对lodash中的deboun ...
- Java版的防抖(debounce)和节流(throttle)
概念 防抖(debounce) 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时 节流(throttle) 当持续触发事件时, ...
- 函数防抖debounce和节流throttle
debounce 函数防抖 1.什么是函数防抖 函数防抖是优化高频率执行 js 代码的一种手段 可以让被调用的函数在一次连续的高频率操作过程中只被调用一次 2.函数防抖的作用 减少代码执行次数,提升网 ...
- 防抖(debounce)和节流(throttle)
针对一些会频繁触发的事件如scroll.resize,如果正常绑定事件处理函数的话,有可能在很短的时间内多次连续触发事件,十分影响性能.防抖和节流就是针对响应跟不上触发频率这类问题的两种解决方案 因此 ...
- 当面试官让你手写防抖、节流时,是在考察什么
防抖.节流,都是用于节省函数调用次数的方案,达到优化程序.提升性能甚至是避免bug的目的.作为一个经典的主题,也是面试常考项,部分面试官会让你手写,这时, 他是在考察什么?你能轻易地写出比较好的防抖. ...
- 手写防抖和节流中的一些细节
使用函数节流与函数防抖的目的,就是为了节约计算机资源,提升用户体验.js中的一些事件如浏览器的resize.scroll,鼠标的mousemove.mouseover,input输入框的keypres ...
最新文章
- 演讲实录丨CAAI名誉副理事长杨强教授:人工智能的金融实践
- hibernate配置文件(简单版)
- boostrap3常用组件集合
- mysql 开启断线重连_[BUG反馈]MYSQL长连接中(SWOOLE) 使用事务提交开启断线重连接抛出异常...
- dbc数据库 与 mysql_使用反应式关系数据库连接规范R2DBC操作MySQL数据库
- 如何自动保存邮件草稿
- Linux 混合编译opencv与opencv_contrib的android版本
- HTML table 和 div
- 在git上面找开源项目遇到的坑
- Bailian2899 Bailian3242 矩阵交换行【矩阵】
- 存储过程循环遍历一个月的每一天的函数_3.3 循环
- Android handler.obtainMessage()传字符串用法
- 软件公司产品营销大数据分析(下)
- cpu(s)和%CPU的的区别
- 硅谷之火:人与计算机的未来
- VIM和sed 替换字符串方法
- linux 手动修复分区表,分区表修复
- Python :图像的手绘效果
- jQuery 3D图片切换动画
- 常用的几个好用的php集成开发环境
热门文章
- 全国计算机技术与软件专业技术资格(水平)考试2022 年下半年网络规划设计师下午试卷Ⅰ
- 计算机网络基础(四)
- xtrabackup备份及恢复
- 图数据库neo4j通过py2neo的查询操作
- python turtle画笑脸_如何用Python画滑稽笑脸
- Vivado 2018.3入门教程(三):生成比特流文件+硬件连接
- 串通招投标有哪些方法?电子化招投标系统怎么遏制串标?
- Ubuntu下使用python读取doc和docx文档的内容
- 华为手机使用百度地图SDK-无法定位/不显示图标的解决方案之一
- 如何计算机房产面积,4计算机在房产面积测算中的应用.pdf