数个月之前,在一次前端的性能优化中,接触到了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的防抖和节流的更多相关文章

  1. JS的防抖与节流

    JS的防抖与节流在进行窗口的resize.scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕.此时我们可以采用debounce(防抖)和t ...

  2. JS的防抖与节流学习笔记

    防抖(debounce):当持续触发事件时,在一定的时间段内,只有最后一次触发的事件才会执行. 例: function debounce(fn, wait) { var timer = null; r ...

  3. js函数防抖、节流实现

    防抖 Debounce 函数防抖就是,延迟一段时间再执行函数,如果这段时间内又触发了该函数,则延迟重新计算: // 简单实现 function debounce(fn, wait) { let t r ...

  4. JS的防抖,节流,柯里化和反柯里化

    今天我们来搞一搞节流,防抖,柯里化和反柯里化吧,是不是一看这词就觉得哎哟wc,有点高大上啊.事实上,我们可以在不经意间用过他们但是你却不知道他们叫什么,没关系,相信看了今天的文章你会有一些收获的 节流 ...

  5. js实现防抖,节流

    防抖函数. 将几次操作合并为一次操作进行.设置一个计时器,规定在延迟时间后触发函数,但是在延迟时间内如果再次触发,就会取消之前的计时器.如此,只有最后一次操作能触发.代码如下: function de ...

  6. 彻底搞懂JavaScript的闭包、防抖跟节流

    最近出去面试了一下,收获颇多!!! 以前的我,追求实际,比较追求实用价值,然而最近面试,传说中的面试造火箭,工作拧螺丝,竟然被我遇到了.虽然很多知识点在实际工作中并不经常用到,但人家就是靠这个来筛选人 ...

  7. js高阶函数应用—函数防抖和节流

    高阶函数指的是至少满足下列两个条件之一的函数: 1. 函数可以作为参数被传递:2.函数可以作为返回值输出: javaScript中的函数显然具备高级函数的特征,这使得函数运用更灵活,作为学习js必定会 ...

  8. js防抖和节流

    今天在网上看到的,里面的内容非常多.说下我自己的理解. 所谓的防抖就是利用延时器来使你的最后一次操作执行.而节流是利用时间差的办法,每一段时间执行一次.下面是我的代码: 这段代码是右侧的小滑块跟随页面 ...

  9. 2019 面试准备 - JS 防抖与节流 (超级 重要!!!!!)

    Hello 小伙伴们,如果觉得本文还不错,记得给个 star , 你们的 star 是我学习的动力!GitHub 地址 本文涉及知识点: 防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 ...

随机推荐

  1. 原生js实现分页效果(带实例)

    小小插件(静态分页) 效果图: 首先实现简单功能: <!DOCTYPE html> <html> <head> <meta http-equiv=" ...

  2. android layout文件优化

    性能优化1--UI优化 1.使用系统为我们提供了几个抽象的标签①include:重用include中layout属性指定一个外部布局文件,通过该方式则不需要把这个布局文件在该代码中重复的写一遍了. 若 ...

  3. 《CSS世界》读书笔记(六)

    <!-- <CSS世界> 张鑫旭著 --> min-width/max-width和min-height/max-height min-width/max-width出现的场景 ...

  4. codeforces #305 E Mike and friends

    原问题可以转化为:给定第k个字符串,求它在L-R的字符串里作为子串出现了多少次 定义子串为字符串的某个前缀的某个后缀(废话) 等价于我们把一个字符串插入到trie里,其过程中每个经过的节点和其向上的f ...

  5. win的使用

    1.net use 挂在远端文件系统,方便本机软件操作! 添加挂载文件   net use  h:   //192.168.1.1/file 删除挂载文件   net use /delete  h: ...

  6. Flutter 控件之 Routes 和 Navigator. [PopupRoute]

    一个 App 通常会有多个界面,每个界面实现不同的功能,并在多个界面之间跳转.在 Flutter 中多个界面的跳转是通过 Navigator 来实现的. 在 Flutter 中定义了一个 Overla ...

  7. nginx 反向代理和正向代理功能 第六章

    一:Nginx作为正向代理服务器: 1.正向代理:代理(proxy)服务也可以称为是正向代理,指的是将服务器部署在公司的网关,代理公司内部员工上外网的请求,可以起到一定的安全作用和管理限制作用,正向代 ...

  8. opencv学习之路(28)、轮廓查找与绘制(七)——位置关系及轮廓匹配

    一.点与轮廓的距离及位置关系 #include "opencv2/opencv.hpp" #include <iostream> using namespace std ...

  9. git分散式版本管理系统,从安装到基本使用

    首先,当然是安装git了,不用寻思,官网下载即可 https://git-scm.com/downloads 第二是设置账户,鼠标右键,选择git bush,在命令窗口中进行设置 git config ...

  10. linux shell中如何往所有行尾添加内容

    答: sed -i 's/$/yes/' jello.txt 这句话的意思就是在jello.txt文件的所有行尾都添加相同的内容yes,如jello.txt原来的内容为: no jello hello ...