javascript中的函数节流和函数去抖

带着问题去尝试

首先我们要知道为什么要用到函数节流和函数去抖?我们带着以下的疑问来进行分析!

1.比如搜索框,你会用到什么事件(change、blur、keyup等)?去做什么效果?
2.再比如scroll滚动事件,怎么去触发?是滚一段距离触发一次?还是滚一圈触发一次?还是滚一次触发一次?
3.还包括mouseover事件是怎么触发呢?
......

场景实例

函数节流和去抖的出现场景,一般都伴随着客户端 DOM 的事件监听。举个例子,实现一个原生的拖拽功能(不能用 H5 Drag&Drop API),需要一路监听 mousemove 事件,在回调中获取元素当前位置,然后重置 dom 的位置(样式改变)。如果我们不加以控制,每移动一定像素而触发的回调数量是会非常惊人的,回调中又伴随着 DOM 操作,继而引发浏览器的重排与重绘,性能差的浏览器可能就会直接假死,这样的用户体验是非常糟糕的。我们需要做的是降低触发回调的频率,比如让它 500ms 触发一次,或者 200ms,甚至 100ms,这个阈值不能太大,太大了拖拽就会失真,也不能太小,太小了低版本浏览器可能就会假死,这样的解决方案就是函数节流,英文名字叫「throttle」。函数节流的核心是,让一个函数不要执行得太频繁,减少一些过快的调用来节流。

说完函数节流,再看它的好基友函数去抖(debounce)。思考这样一个场景,对于浏览器窗口,每做一次 resize 操作,发送一个请求,很显然,我们需要监听 resize 事件,但是和 mousemove 一样,每缩小(或者放大)一次浏览器,实际上会触发 N 多次的 resize 事件,用节流?节流只能保证定时触发,我们一次就好,这就要用去抖。简单的说,函数去抖就是对于一定时间段的连续的函数调用,只让其执行一次。

实例了解

下面就让我们来了解throttle(节流) 和 debounce(去抖)

1.throttle节流,scroll和mouseover亦或者其他方式,每次移动都会触发代码效果,但是这些效果太密集了,占用了系统资源,计算机的计算能力是有限的,我们写的代码应该尽可能的优雅。
2.debounce去抖,本意是从按键去抖过来的,让我们的用户正确的操作之后才去执行代码,且只会执行一次,比如当我们做文本输入的时候,如果用keyup我们不是去节流,而是去判断用户停止了输入。
3.节流保证在一定时间内,只能触发一次。如果我们只要触发一次,这就是去抖。代码上来看差距不是很大。

直接试一下:

//先来个有问题的代码
window.onscroll=function(){
    console.log(new Date());
}

控制台会打印:

VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)...

控制台会一直这样输入,那问题来了,这获取并不是我们想要的,我们并不想让他一直触发下去。

我们要解决这些问题,所以直接看代码:

//我们先来个节流,每秒输出一次
window.onscroll=function(){
    if(window.onScrollTag == undefined){
        window.onScrollTag=true;
        console.log(new Date());
        setTimeout(function(){
            window.onScrollTag=undefined;
        },1000);
    }
}//先触发
window.onscroll=function(){
    if(window.onScrollTag == undefined){
        window.onScrollTag=setTimeout(function(){
            window.onScrollTag=undefined;
             console.log(new Date());
        },1000);

    }
}//后触发
//从上面的代码可以看出来,我们在一个事件执行的时候就把标记改成不可用。一秒后才可以再次触发操作。
//我们在尝试一下去抖
window.onscroll=function(){
    if(window.onScrollTag != undefined){
        clearTimeout(window.onScrollTag);
    }
    window.onScrollTag=setTimeout(function(){
         console.log(new Date());
    },1000);
}//消抖,消除抖动,感觉这个更好听
//节流
funtion throttle(func, wait) {  
    var lastTime = 0,
        timeout;  
    return funtion() {    
        var context = this,
            args = arguments,
            delay = wait || 100,
            now = new Date().getTime();    
        if (now - lastTime <= delay) {      
            return;    
        }    
        lastTime = now;
        clearTimeout(timeout);  
        timeout = setTimeout(function() {
            timeout = null;
            func.apply(context, args);
        }, delay)  
    }
}
// 去抖
function debounce(func, wait) {
    var timeout;
    return function() {
        var context = this,
            args = arguments,
            delay = wait || 250;
        clearTimeout(timeout);
        timeout = setTimeout(function() {
            timeout = null;
            func.apply(context, args);
        }, delay);
    };
}

throttle 应用场景

函数节流有哪些应用场景?哪些时候我们需要间隔一定时间触发回调来控制函数调用频率?

  • DOM 元素的拖拽功能实现(mousemove)
  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
  • 计算鼠标移动的距离(mousemove)
  • Canvas 模拟画板功能(mousemove)
  • 搜索联想(keyup)
  • 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次

debounce 应用场景

函数去抖有哪些应用场景?哪些时候对于连续的事件响应我们只需要执行一次回调?

  • 每次 resize/scroll 触发统计事件
  • 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)

小结

函数节流和函数去抖的核心其实就是限制某一个方法被频繁触发,而一个方法之所以会被频繁触发,大多数情况下是因为 DOM 事件的监听回调,而这也是函数节流以及去抖多数情况下的应用场景

如果大家感兴趣,可以参考下:http://underscorejs.org/

时间: 2024-10-12 07:26:21

javascript中的函数节流和函数去抖的相关文章

JavaScript中常见的数组操作函数及用法

昨天写了个帖子,汇总了下常见的JavaScript中的字符串操作函数及用法.今天正好有时间,也去把JavaScript中常见的数组操作函数及用法总结一下,这样方便大家准备参考.如果恰好你也在准备各种笔试,希望对你有所帮助.同时,也欢迎补充. 1.数组创建 创建数组应该是最简单的了,有用数组字面量创建和数组构造函数两种方法,见下: var array1 = new Array(); var array2 = []; 上面是创建数组的最常见的两种方法,其中第二种方法因为简单直观而被开发者推崇.其中,

函数节流和函数去抖

函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段. 以下场景往往由于事件频繁被触发,因而频繁执行DOM操作.资源加载等重行为,导致UI停顿甚至浏览器崩溃. 1. window对象的resize.scroll事件 2. 拖拽时的mousemove事件 3. 射击游戏中的mousedown.keydown事件 4. 文字输入.自动完成的keyup事件 实际上对于window的resize事件,实际需求大多为停止改变大小n毫秒后执行后续处理:而其他事件大多的需求是以一定的频率执行后续处理.

一篇文章把你带入到JavaScript中的闭包与高级函数

在JavaScript中,函数是一等公民.JavaScript是一门面向对象的编程语言,但是同时也有很多函数式编程的特性,如Lambda表达式,闭包,高阶函数等,函数式编程时一种编程范式. function dada() { var a = 1; var b = function() { console.log(a); } return b // b 就是一个闭包函数,因为它能访问dada函数的作用域 } JavaScript的函数也是对象,可以有属性,可以赋值给一个变量,可以放在数组里作为元素

JavaScript中取得反正切的Atan函数

JavaScript中取得反正切的Atan函数 atan 方法:返回数字的反正切值. 使用方式如下: Math.atan(number)http://www.mlyrx120.com 注意:必选项number 参数是需要计算反正切的数值表达式.返回值为其数字参数的反正切值.

JavaScript函数节流和函数防抖的原理与区别

一.概念解释 ?函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段.?大家大概都知道旧款电视机的工作原理,就是一行行得扫描出色彩到屏幕上,然后组成一张张图片.由于肉眼只能分辨出一定频率的变化,当高频率的扫描,人类是感觉不出来的.反而形成一种视觉效果,就是一张图.就像高速旋转的风扇,你看不到扇叶,只看到了一个圆一样.?同理,可以类推到js代码.在一定时间内,代码执行的次数不一定要非常多.达到一定频率就足够了.因为跑得越多,带来的效果也是一样.倒不如,把js代码的执行次数控制在合理的范围.

JavaScript函数节流和函数防抖之间的区别

一.概念解释 ?函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段.?大家大概都知道旧款电视机的工作原理,就是一行行得扫描出色彩到屏幕上,然后组成一张张图片.由于肉眼只能分辨出一定频率的变化,当高频率的扫描,人类是感觉不出来的.反而形成一种视觉效果,就是一张图.就像高速旋转的风扇,你看不到扇叶,只看到了一个圆一样.?同理,可以类推到js代码.在一定时间内,代码执行的次数不一定要非常多.达到一定频率就足够了.因为跑得越多,带来的效果也是一样.倒不如,把js代码的执行次数控制在合理的范围.

javascript中可用的编码解码函数

在项目实践中可能会遇到一些特殊字符的转义问题,那么这个时候就需要js编码解码函数来解决这些情况了: 特殊字符的含义 URL编码  符号 解释 转义 # 用来标志特定的文档位置 %23 % 对特殊字符进行编码 %25 & 分隔不同的变量值对 %26 + 在变量值中表示空格 %2B / 表示目录路径 %2F \ 表示目录路径 %5C = 用来连接键和值 %3D ? 表示查询字符串的开始 %3F 空格 空格 %20 . 句号 %2E : 冒号 %3A javascript中可用的编码解码函数,有如下的

函数节流与函数去抖

函数节流与函数去抖都是为了解决密集的js函数运行问题.怎么分析和使用两种情况呢? 函数节流: 是指函数在一段时间执行一次,即降低函数运行的频率.比如说,在onmousemove时,进行一次dom操作,如果长时间的onmousemove,这样所触发回调数量是大量的,因为进行了大量的dom操作,可能导致浏览器无响应.这时候就可以听过函数节流,使一段时间触发一次回调函数,大大降低了消耗. var ifRun = true; function run () { if (!ifRun) { return;

JavaScript函数节流与函数去抖

介绍 首先解释一下这两个概念: 函数节流(throttle):是让一个函数无法在很短的时间间隔内连续调用,当上一次函数执行后过了规定的时间间隔,才能进行下一次该函数的调用. 函数去抖(debounce):让一个函数在一定间隔内没有被调用时,才开始执行被调用方法. 两个方法都是用来提升前端性能,减轻浏览器压力. 应用 理解起来有点费力,通过应用来理解就轻松了.通常,我们会在有用户交互参与的地方添加事件,而往往这种事件会被频繁触发. 想象一下窗口的resize事件或者是一个元素的onmousemov