前端性能优化的利器 ——— 浅谈JavaScript中的防抖和节流

防抖和节流函数是工作中两种常用的前端性能优化函数,今天我就来总结一下什么是防抖和节流,并详细说明一下如何在工作中应用防抖和节流函数

什么是防抖和节流?

在 JavaScript 中,防抖(debounce)和节流(throttle)是用来限制函数执行频率的两种常见技术。

防抖(debounce) 是指在某个时间段内,只执行最后一次触发的函数调用。如果在这个时间段内再次触发该函数,会重新计时,直到等待时间结束才会执行函数。
这个技术通常用于处理频繁触发的事件,比如窗口大小调整、搜索框输入等。防抖可以避免函数执行过多次,以减少网络开销和性能负担。

节流(throttle) 是指在一段时间内限制函数的执行频率,保证一定时间内只执行一次函数调用。无论触发频率多高,都会在指定时间间隔内执行一次函数。
这个技术通常用于处理连续触发的事件,比如滚动事件、鼠标移动事件等。节流可以控制函数的执行频率,以减少资源消耗和提高性能。

手写一个防抖的工具函数

function debounce(func, delay) {
  let timeoutId;
  
  return function() {
    const context = this;
    const args = arguments;
    
    clearTimeout(timeoutId);
    
    timeoutId = setTimeout(function() {
      func.apply(context, args);
    }, delay);
  };
}

函数说明

  1. 这个防抖函数接受两个参数:func表示需要进行防抖的函数,delay表示延迟的时间间隔(以毫秒为单位)
  2. 函数内部使用了一个timeoutId变量来保存定时器的标识。当调用防抖函数返回的新函数时,会清除之前的定时器,并设置一个新的定时器。只有在延迟时间内没有再次调用该新函数时,才会触发最终的函数执行

使用示例

该示例表示在全局滚动事件中使用防抖函数,每200毫秒内如果触发滚动事件,那么不会执行handleScroll()函数。
然后重新计时200毫秒,再次判断,直到最后一个200毫秒内没有触发滚动事件,才会执行handleScroll()函数

function handleScroll() {
  console.log('Scrolled');
}
const debouncedScroll = debounce(handleScroll, 200);
window.addEventListener('scroll', debouncedScroll);

手写一个节流的工具函数

function throttle(func, delay) {
  let timeoutId;
  let lastExecTime = 0;

  return function(...args) {
    const currentTime = Date.now();
    const remainingTime = delay - (currentTime - lastExecTime);

    clearTimeout(timeoutId);

    if (remainingTime <= 0) {
      func.apply(this, args);
      lastExecTime = currentTime;
    } else {
      timeoutId = setTimeout(() => {
        func.apply(this, args);
        lastExecTime = Date.now();
      }, remainingTime);
    }
  };
}

函数说明

  1. 这个节流函数接受两个参数:func是要执行的函数,delay是延迟时间(以毫秒为单位)
  2. 它返回一个新的函数,该函数在调用时会根据指定的延迟时间来限制原始函数的执行频率

使用示例

在全局滚动事件中使用节流函数,无论在滚动事件的监听过程中,触发了几次handleScroll()函数,都只会在每200毫秒内执行一次handleScroll()函数。

function handleScroll() {
  console.log('Scrolled');
}
const throttledScroll = throttle(handleScroll, 200);
window.addEventListener('scroll', throttledScroll);

如何在工作中应用防抖和节流

防抖和节流主要应用于:搜索框输入事件监听、窗口大小调整事件监听、按钮点击事件监听、滚动事件监听、鼠标移动事件监听等等场景。

工作中哪些场景可以使用防抖函数?

  1. 用户输入: 当用户在表单输入框中频繁输入时,可以使用防抖函数来延迟处理用户输入,避免频繁的请求或操作,提高性能和用户体验。
  2. 搜索框: 在搜索框中,当用户连续输入关键字时,可以使用防抖函数来延迟发送搜索请求,以避免请求过多。
  3. 窗口调整: 当窗口大小调整时,会触发resize事件,可以使用防抖函数来限制resize事件的触发次数,避免频繁执行调整相关的代码。
  4. 按钮频繁点击: 当按钮被频繁点击时,可以使用防抖函数来限制按钮点击的触发次数。

工作中哪些场景可以使用节流函数?

  1. 用户输入: 当用户在文本框中输入时,触发搜索功能。使用节流函数可以限制搜索请求的频率,以避免频繁的网络请求。例如,可以设置一个定时器,在用户输入后的一小段时间内不触发搜索请求,只在定时器结束后才进行搜索。
  2. 无限加载: 当用户滚动页面时,触发加载更多数据的操作。使用节流函数可以限制加载操作的频率,以提高页面的响应性能。例如,可以设置一个定时器,在用户滚动过程中只触发加载操作的最后一次滚动事件。
  3. 按钮频繁点击: 当用户频繁点击某个按钮时,触发某个操作。使用节流函数可以限制点击操作的频率,以避免重复操作或者混乱的界面状态。例如,可以设置一个定时器,在用户点击后的一小段时间内不触发重复操作。

如何使用loadsh.js工具库中的防抖和节流函数

实际开发过程中,我们的项目中可能会直接使用loadsh.js工具库,来避免重复造轮子,所以这里也特地说明一下如何使用loadsh.js工具库中的防抖和节流函数

  1. 安装loadsh.js工具库
npm install lodash  
  1. 在项目中引入loadsh.js工具库,不同前端项目引入方式不同,请自行鉴别
import { debounce, throttle } from 'loadsh';
  1. 使用防抖函数,该示例中,submitData()函数被限制为每1秒只会执行最后一次,如果在等待时间内多次调用该函数,则会重置1秒的等待时间
// 定义要延迟执行的函数
function submitData(data) {
  console.log('保存数据:', data);
}

// 使用debounce函数创建一个延迟执行的函数
const debouncedFn = _.debounce(submitData, 1000);

// 模拟连续触发保存数据的操作
// 等待1秒后,只会执行最后一次保存数据的操作
debouncedFn('数据1'); // 不会输出
debouncedFn('数据2'); // 不会输出
debouncedFn('数据3'); //  输出 —— 保存数据:数据3

  1. 使用节流函数,该示例中,throttledFn()函数被限制为每秒只能执行一次,如果在等待时间内多次调用该函数,则不会执行
// 定义要减少调用次数的函数
function fetchData(data) {
    console.log('拉取数据:', data);
}

// 使用throttle函数创建一个定时执行的函数
const throttledFn = _.throttle(fetchData, 2000);

// 调用throttledFn函数
throttledFn('数据1'); // 输出 —— 拉取数据: 数据1

// 在1秒内多次调用throttledFn函数
throttledFn('数据2'); // 不会输出

// 2秒后再次调用throttledFn函数
setTimeout(() => {
  throttledFn('数据3'); // 输出 —— 拉取数据: 数据3
}, 1000);

我是 fx67ll.com,如果您发现本文有什么错误,欢迎在评论区讨论指正,感谢您的阅读!
如果您喜欢这篇文章,欢迎访问我的 本文github仓库地址,为我点一颗Star,Thanks~ :)
转发请注明参考文章地址,非常感谢!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容