当前位置: 首页 > news >正文

面试官:请说说JS中的防抖和节流

给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:web前端面试题库

前言

为什么要做性能优化?性能优化到底有多重要?   性能优化是为了提供更好的用户体验加快网站加载速度提高搜索引擎排名节省服务器资源适应多种设备和网络环境等方面的需求。通过不断优化性能,可以提高用户满意度、增加网站流量提高业务效果。

同时性能优化是把双刃剑,有好的一面也有坏的一面。好的一面就是可以能提升网站性能,坏的一面就是配置多,代码复杂,或者要遵守的规则太多。并且某些性能优化规则并不适用所有场景,所以也并不是一味的追求性能优化,而是需要谨慎使用。

防抖和节流JavaScript 中常用的两种性能优化方式。面试中我们也会经常碰到。它们的作用是减少函数的执行次数,以提高代码的性能。

在进行窗口的resize、scroll、输出框内容校验等操纵的时候,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常之差。那么为了前端性能的优化也为了用户更好的体验,就可以采用防抖(debounce)和节流(throttle)的方式来到达这种效果,减少调用的频率。

防抖(Debounce)

1. 情景

  • 有些场景事件触发的频率过高(mousemoveonkeydownonkeyuponscroll),例如文本编辑器实时保存,当无任何更改操作一秒后进行保存;调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖。

  • 回调函数执行的频率过高也会有卡顿现象。 可以一段时间过后进行触发去除无用操作

2. 防抖原理

一定在事件触发 n 秒后才执行,如果在一个事件触发的 n 秒内又触发了这个事件,以新的事件的时间为准,n 秒后才执行,等触发事件 n 秒内不再触发事件才执行。

官方解释:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。(ps:个人理解这就相当于游戏中的回城键,只有读秒到规定时间点才会触发回城,期间任意时间打断都会重新计时。)

3. 防抖函数简单实现

    //简单的防抖函数function debounce(func, wait, immediate) {//定时器变量var timeout;return function () {//每次触发scrolle,先清除定时器clearTimeout(timeout);//指定多少秒后触发事件操作handlertimeout = setTimeout(func, wait);};};//绑定在scrolle事件上的handlerfunction handlerFunc() {console.log('Success');}//没采用防抖动window.addEventListener('scroll', handlerFunc);//采用防抖动window.addEventListener('scrolle', debounce(handlerFunc, 1000));

4. 防抖函数演化过程

(1)this event绑定问题

    //以闭包的形式返回一个函数,内部解决了this指向的问题,event对象传递的问题function debounce(func, wait) {var timeout;return function () {var context = this;var args = arguments;clearTimeout(timeout)timeout = setTimeout(function () {func.apply(context, args)}, wait);};};

(2) 立即触发问题

    //首次触发执行,再次触发以后开始执行防抖函数//使用的时候不用重复执行这个函数,本身返回的函数才具有防抖功能
function debounce(func, wait, immediate) {var timeout;return function () {var context = this;var args = arguments;if(timeout) clearTimeout(timeout);// 是否在某一批事件中首次执行if (immediate) {var callNow = !timeout;timeout = setTimeout(function() {timeout = null;func.apply(context, args)immediate = true;}, wait);if (callNow) {func.apply(context, args)}immediate = false;} else {timeout = setTimeout(function() {func.apply(context, args);immediate = true;}, wait);}}
}

(3)返回值问题

function debounce(func, wait, immediate) {var timeout, result;return function () {var context = this, args = arguments;if (timeout)  clearTimeout(timeout);if (immediate) {var callNow = !timeout;timeout = setTimeout(function() {result = func.apply(context, args)}, wait);if (callNow) result = func.apply(context, args);} else {timeout = setTimeout(function() {result = func.apply(context, args)}, wait);}return result;}
}

(4)取消防抖,添加cancel方法

function debounce(func, wait, immediate) {var timeout, result;function debounced () {var context = this, args = arguments;if (timeout)  clearTimeout(timeout);if (immediate) {var callNow = !timeout;timeout = setTimeout(function() {result = func.apply(context, args)}, wait);if (callNow) result = func.apply(context, args);} else {timeout = setTimeout(function() {result = func.apply(context, args)}, wait);}return result;}debounced.cancel = function(){cleatTimeout(timeout);timeout = null;}return debounced;
}

节流(Throttle)

1.情景

  • 图片懒加载
  • ajax数据请求加载

2.节流原理

如果持续触发事件,每隔一段时间只执行一次函数,控制了事件发生的频率。

官方解释:当持续触发事件时,保证一定时间段内只调用一次事件处理函数。(s:个人理解这就相当于游戏中的射击,就算你高频点击,子弹只会在固定时间段内射出。)

3.节流实现-时间戳和定时器

  • 时间戳
    var throttle = function (func, delay) {var prev = Date.now()return function () {var context = this;var args = arguments;var now = Date.now();if (now - prev >= delay) {func.apply(context, args);prev = Date.now();}}}function handle() {console.log(Math.random());}window.addEventListener('scroll', throttle(handle, 1000));
  • 定时器
    var throttle = function (func, delay) {var timer = null;return function () {var context = this;var args = arguments;if (!timer) {timer = setTimeout(function () {func.apply(context, args);timer = null;}, delay);}}}function handle() {console.log(Math.random());}window.addEventListener('scroll', throttle(handle, 1000))

4.节流函数的演化过程

  • 时间戳触发
//在开始触发时,会立即执行一次; 如果最后一次没有超过 wait 值,则不触发
function throttle(func, wait) {var context, args;var previous = 0; // 初始的时间点,也是关键的时间点return function() {var now = +new Date();context = this;args = arguments;if (now - previous > wait) {func.apply(context, args);previous = now;}}
}
  • 定时器触发
//首次不会立即执行,最后一次会执行,和用时间戳的写法互补。
function throttle(func, wait){var context, args, timeout;return function() {context = this;args = arguments;if(!timeout) {timeout = setTimeout(function(){func.apply(context, args);timeout = null;}, wait);}}
}
  • 结合时间戳和定时器
function throttle(func, wait) {var timer = null;var startTime = Date.now();  return function(){var curTime = Date.now();var remaining = wait-(curTime-startTime); var context = this;var args = arguments;clearTimeout(timer);if(remaining<=0){ func.apply(context, args);startTime = Date.now();}else{timer = setTimeout(fun, remaining);  // 如果小于wait 保证在差值时间后执行}}
}

总结

防抖:原理是维护一个定时器,将很多个相同的操作合并成一个。规定在delay后触发函数,如果在此之前触发函数,则取消之前的计时重新计时,只有最后一次操作能被触发

节流:原理是判断是否达到一定的时间来触发事件。某个时间段内只能触发一次函数

区别:防抖只会在最后一次事件后执行触发函数,节流不管事件多么的频繁,都会保证在规定时间段内触发事件函数。

给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:web前端面试题库

http://www.lryc.cn/news/251877.html

相关文章:

  • [足式机器人]Part4 南科大高等机器人控制课 Ch00 课程简介
  • SSM项目实战-登录验证成功并路由到首页面,Vue3+Vite+Axios+Element-Plus技术
  • Python----网络爬虫
  • 【微信小程序】上传头像 微信小程序内接小程序客服
  • 【c++随笔15】c++常用第三方库
  • 数据结构 | 查漏补缺之ASL、
  • 泊车功能专题介绍 ———— 汽车全景影像监测系统性能要求及试验方法(国标未公布)
  • 【Linux】第二十六站:软硬链接
  • 开源播放器GSYVideoPlayer + ViewPager2 源码解析
  • 重启路由器可以解决N多问题?
  • Python WebSocket 客户端教程
  • 洛谷 P2984 [USACO10FEB] Chocolate Giving S
  • 【专题】【数列极限】
  • oracle基础系统学习文章目录
  • 长度最小的子数组(Java详解)
  • 计算机组成学习-数据的表示和运算总结
  • 目标检测YOLO系列从入门到精通技术详解100篇-【目标检测】机器视觉(基础篇)(八)
  • 【4】基于多设计模式下的同步异步日志系统-框架设计
  • Jupyter Markdown 插入图片
  • web自动化 -- pyppeteer
  • Java 数组另类用法(字符来当数组下标使用)
  • error转string
  • Android监听用户的截屏、投屏、录屏行为
  • MATLAB算法实战应用案例精讲-【路径规划】 图搜索算法
  • Elasticsearch-Kibana使用教程
  • mysql(八)docker版Mysql8.x设置大小写忽略
  • KALI LINUX攻击与渗透测试
  • vue之mixin混入
  • [ffmpeg] find 编码器
  • Android CardView基础使用