JS的防抖和节流
数个月之前,在一次前端的性能优化中,接触到了JS中防抖和节流,一开始还不明白他们的应用在哪里,可后来才知道,这是前端中最基础的性能优化,在绑定 scroll 、resize 这类事件时,当它发生时,它被触发的频次非常高,间隔很近。如果事件中涉及到大量的位置计算、DOM 操作、元素重绘等工作且这些工作无法在下一个 scroll 事件触发前完成,就会造成浏览器掉帧。加之用户鼠标滚动往往是连续的,就会持续触发 scroll 事件导致掉帧扩大、浏览器 CPU 使用率增加、用户体验受到影响。尤其是在涉及与后端的交互中,前端依赖于某种事件如resize,scroll,发送Http请求,在这个过程中,如果不做防抖处理,那么在事件触发的一瞬间,会有很多个请求发过去,增加了服务端的压力。今天又接触到一个项目,里面的响应式做的非常到位,同时性能优化做的非常好,所以想把JS的防抖和节流做一个总结。(大佬不喜勿喷)
一、函数防抖(debounce)
当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。如下图,持续触发scroll事件时,并不执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发scroll事件。
下面通过一段代码来演示一个防抖的例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body{
height: 5000px;
}
</style>
</head>
<body>
<script>
function debounce(fn, wait) {
var timeout = null;
return function() {
if(timeout !== null)
clearTimeout(timeout);
timeout = setTimeout(fn, wait);
}
}
// 处理函数
function handle() {
console.log(Math.random());
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));
</script>
</body>
</html>
大概的效果就是这个样子:
这是我自己的运行结果:
二、函数节流(throttle)
当持续触发事件时,保证一定时间段内只调用一次事件处理函数。节流通俗解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴。如下图,持续触发scroll事件时,并不立即执行handle函数,每隔1000毫秒才会执行一次handle函数。
时间戳方案
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));
时间戳+定时器
var throttle = function(func, delay) {
var timer = null;
var startTime = Date.now();
return function() {
var curTime = Date.now();
var remaining = delay - (curTime - startTime);
var context = this;
var args = arguments;
clearTimeout(timer);
if (remaining <= 0) {
func.apply(context, args);
startTime = Date.now();
} else {
timer = setTimeout(func, remaining);
}
}
}
function handle() {
console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));
效果如下:
三、总结
函数防抖:将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
函数节流:使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。
区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。
JS的防抖和节流的更多相关文章
- JS的防抖与节流
JS的防抖与节流在进行窗口的resize.scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕.此时我们可以采用debounce(防抖)和t ...
- JS的防抖与节流学习笔记
防抖(debounce):当持续触发事件时,在一定的时间段内,只有最后一次触发的事件才会执行. 例: function debounce(fn, wait) { var timer = null; r ...
- js函数防抖、节流实现
防抖 Debounce 函数防抖就是,延迟一段时间再执行函数,如果这段时间内又触发了该函数,则延迟重新计算: // 简单实现 function debounce(fn, wait) { let t r ...
- JS的防抖,节流,柯里化和反柯里化
今天我们来搞一搞节流,防抖,柯里化和反柯里化吧,是不是一看这词就觉得哎哟wc,有点高大上啊.事实上,我们可以在不经意间用过他们但是你却不知道他们叫什么,没关系,相信看了今天的文章你会有一些收获的 节流 ...
- js实现防抖,节流
防抖函数. 将几次操作合并为一次操作进行.设置一个计时器,规定在延迟时间后触发函数,但是在延迟时间内如果再次触发,就会取消之前的计时器.如此,只有最后一次操作能触发.代码如下: function de ...
- 彻底搞懂JavaScript的闭包、防抖跟节流
最近出去面试了一下,收获颇多!!! 以前的我,追求实际,比较追求实用价值,然而最近面试,传说中的面试造火箭,工作拧螺丝,竟然被我遇到了.虽然很多知识点在实际工作中并不经常用到,但人家就是靠这个来筛选人 ...
- js高阶函数应用—函数防抖和节流
高阶函数指的是至少满足下列两个条件之一的函数: 1. 函数可以作为参数被传递:2.函数可以作为返回值输出: javaScript中的函数显然具备高级函数的特征,这使得函数运用更灵活,作为学习js必定会 ...
- js防抖和节流
今天在网上看到的,里面的内容非常多.说下我自己的理解. 所谓的防抖就是利用延时器来使你的最后一次操作执行.而节流是利用时间差的办法,每一段时间执行一次.下面是我的代码: 这段代码是右侧的小滑块跟随页面 ...
- 2019 面试准备 - JS 防抖与节流 (超级 重要!!!!!)
Hello 小伙伴们,如果觉得本文还不错,记得给个 star , 你们的 star 是我学习的动力!GitHub 地址 本文涉及知识点: 防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 ...
随机推荐
- 前端学习历程--css①
---恢复内容开始--- 本文用自己的理解,总结网上或者自身经历的问题,加以汇总,方便查找: 一.浏览器默认样式 1.浏览器处理css&html a.css作用范围:盒子模式.浮动.定位.背景 ...
- [ Python ] OpenGL
pyOpenGL Installation Package Version------------------- -------numpy 1.14.2 PyOpenGL 3.1.0 PyOpenGL ...
- 18 os/os.path模块中关于文件/目录常用的函数使用方法 (转)
os模块中关于文件/目录常用的函数使用方法 函数名 使用方法 getcwd() 返回当前工作目录 chdir(path) 改变工作目录 listdir(path='.') 列举指定目录中的文件名('. ...
- 用java生成32位全球唯一的id编号
GUID是一个128位长的数字,一般用16进制表示.算法的核心思想是结合机器的网卡.当地时间.一个随即数来生成GUID.从理论上讲,如果一台机器每秒产生10000000个GUID,则可以保证(概率意义 ...
- consul 集群
主机运行 : consul agent -server -bootstrap-expect 2 -data-dir D:\consul -node=winyh -bind=192.168.10.1 ...
- fpga板制作调试过程记录
2010-09-11 22:49:00 昨天淘宝准备买块fpga核心板学习,为了练习焊接,我让老板给我散料及pcb板自己焊接. 一,在物料到之前的准备: 我先设计了一下焊接测试计划 1,检查电路板:特 ...
- Porsche Piwis Tester II V14.000 with CF30 Laptop at autonumen.com
Porsche piwis tester ii is the latest professional tester for Porshe,the most poweful diagnose and o ...
- Python Semaphore
Semaphore信号量的使用 信号量: 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人 ...
- Linux 查看磁盘读写速度IO使用情况
# 查看io进程 命令:iotop 注:DISK TEAD:n=磁盘读/每秒 DISK WRITE:n=磁盘写/每秒. 注:标黄的可查看磁盘的读写速率,下面可以看到使用的io ...
- C++读写图片数据转成Base64格式的一种方法
最近在一个项目中要实现在客户端和服务端之间传送图片文件的功能,采用了C++语言读写图片转化成Base64格式进行传输.具体代码如下: //++Base64.h #pragma once class C ...