目录

测试代码

防抖(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)相关推荐

  1. 防抖debounce和节流throttle

    大纲 一.出现缘由 二.什么是防抖debounce和节流throttle 三.应用场景 3.1防抖 3.2节流 一.出现缘由 前端开发中,有一部分用户行为会频繁触发事件,而对于DOM操作,资源加载等耗 ...

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

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

  3. 函数防抖(debounce)和节流(throttle)以及lodash的debounce源码赏析

    函数节流和去抖的出现场景,一般都伴随着客户端 DOM 的事件监听.比如scroll resize等事件,这些事件在某些场景触发非常频繁. 比如,实现一个原生的拖拽功能(不能用 H5 Drag& ...

  4. 探究防抖(debounce)和节流(throttle)

    本文来自我的博客,欢迎大家去GitHub上star我的博客 本文从防抖和节流出发,分析它们的特性,并拓展一种特殊的节流方式requestAnimationFrame,最后对lodash中的deboun ...

  5. Java版的防抖(debounce)和节流(throttle)

    概念 防抖(debounce) 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时 节流(throttle) 当持续触发事件时, ...

  6. 函数防抖debounce和节流throttle

    debounce 函数防抖 1.什么是函数防抖 函数防抖是优化高频率执行 js 代码的一种手段 可以让被调用的函数在一次连续的高频率操作过程中只被调用一次 2.函数防抖的作用 减少代码执行次数,提升网 ...

  7. 防抖(debounce)和节流(throttle)

    针对一些会频繁触发的事件如scroll.resize,如果正常绑定事件处理函数的话,有可能在很短的时间内多次连续触发事件,十分影响性能.防抖和节流就是针对响应跟不上触发频率这类问题的两种解决方案 因此 ...

  8. 当面试官让你手写防抖、节流时,是在考察什么

    防抖.节流,都是用于节省函数调用次数的方案,达到优化程序.提升性能甚至是避免bug的目的.作为一个经典的主题,也是面试常考项,部分面试官会让你手写,这时, 他是在考察什么?你能轻易地写出比较好的防抖. ...

  9. 手写防抖和节流中的一些细节

    使用函数节流与函数防抖的目的,就是为了节约计算机资源,提升用户体验.js中的一些事件如浏览器的resize.scroll,鼠标的mousemove.mouseover,input输入框的keypres ...

最新文章

  1. 演讲实录丨CAAI名誉副理事长杨强教授:人工智能的金融实践
  2. hibernate配置文件(简单版)
  3. boostrap3常用组件集合
  4. mysql 开启断线重连_[BUG反馈]MYSQL长连接中(SWOOLE) 使用事务提交开启断线重连接抛出异常...
  5. dbc数据库 与 mysql_使用反应式关系数据库连接规范R2DBC操作MySQL数据库
  6. 如何自动保存邮件草稿
  7. Linux 混合编译opencv与opencv_contrib的android版本
  8. HTML table 和 div
  9. 在git上面找开源项目遇到的坑
  10. Bailian2899 Bailian3242 矩阵交换行【矩阵】
  11. 存储过程循环遍历一个月的每一天的函数_3.3 循环
  12. Android handler.obtainMessage()传字符串用法
  13. 软件公司产品营销大数据分析(下)
  14. cpu(s)和%CPU的的区别
  15. 硅谷之火:人与计算机的未来
  16. VIM和sed 替换字符串方法
  17. linux 手动修复分区表,分区表修复
  18. Python :图像的手绘效果
  19. jQuery 3D图片切换动画
  20. 常用的几个好用的php集成开发环境

热门文章

  1. 全国计算机技术与软件专业技术资格(水平)考试2022 年下半年网络规划设计师下午试卷Ⅰ
  2. 计算机网络基础(四)
  3. xtrabackup备份及恢复
  4. 图数据库neo4j通过py2neo的查询操作
  5. python turtle画笑脸_如何用Python画滑稽笑脸
  6. Vivado 2018.3入门教程(三):生成比特流文件+硬件连接
  7. 串通招投标有哪些方法?电子化招投标系统怎么遏制串标?
  8. Ubuntu下使用python读取doc和docx文档的内容
  9. 华为手机使用百度地图SDK-无法定位/不显示图标的解决方案之一
  10. 如何计算机房产面积,4计算机在房产面积测算中的应用.pdf