前言:

        本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽。

        函数防抖与节流是做什么的?下面进行通俗的讲解。

本文借鉴:https://www.cnblogs.com/cc-freiheit/p/10827372.html

大致原理:

        函数防抖:   函数防抖做一件事,这件事并不是立即去做,而是等到一段时间之后再去做。如果这段时间内有一个东西再次触发了,那么就再等一次时间。

        函数节流:   函数节流是指在某一段时间,去执行意见事,但是他不会重新停止计时,他只能保证在某一段时间内运行一次。

函数节流与函数防抖的区别:

    函数节流是固定一段时间运行,会持续触发事件。函数防抖则是在一段事件内运行一次以后不会持续触发事件,要等一段时间才会再次触发。

准备工作:

    <div class="text"
        style="height:150px; line-height:150px; text-align:center; color:#000000; background-color:rgb(212, 233, 163); font-size:80px;">
    </div>

    <script>
        var text = document.querySelector('.text');
        var num = 1;
        function count() {
            text.innerHTML = num++;
        };
        text.onmousemove = debounce(count, 1000);
    </script>

    上面代码运行时,鼠标在绿色区域移动时,由于count函数的持续触发,会导致下图效果

  

    为了避免频繁触发,我们可以使用函数防抖函数节流来限制频繁触发

函数防抖:

    // 非立即执行版
    <script>
        function debounce(callback, time) {
            var timer;
            return function () {
                var args = arguments;
                var self = this;
                if (timer) {
                    clearTimeout(timer);
                }
                timer = setTimeout(function () {
                    callback.apply(self, args);
                }, time)
            }
        }
    </script>

使用方法:

text.onmousemove = debounce(count, 1000);

非立即执行版的意思是触发事件后函数不会立即执行,而是在 time秒后执行,如果在 time 秒内又触发了事件,则会重新计算函数执行时间。(鼠标移出元素时还会触发最后一次)效果如下:

  

    // 立即执行版
    <script>
        function debounce(callback, time) {
            var timer;
            return function () {
                var args = arguments;
                var self = this;
                if (timer) {
                    clearTimeout(timer);
                }
                var callNow = !timer;
                timer = setTimeout(function () {
                    timer = null;
                }, time);
                if (callNow) {
                    callback.apply(self, args);
                }
            }
        }
    </script>

立即执行版的意思是触发事件后函数会立即执行,然后 time 秒内不触发事件才能继续执行函数的效果。用法同上。(鼠标移出元素时,视time的间隔而确定是否触发最后一次)效果如下

  

函数节流:

<script>
        //  定时器版
        function throttle(callback, time) {
            var timer;
            return function () {
                if(timer) {
                    return;
                }
                var args = arguments;
                var self = this;
                timer = setTimeout(function () {
                    callback.apply(self, args);
                    timer = null;
                },time);
            }
        }
</script>

使用方法:

text.onmousemove = throttle(count, 1000);

效果如下

  

定时器执行版的意思是在持续触发事件的过程中,函数不会立即执行,并且每 1s 执行一次。(在移出触发事件后,函数还会再执行一次。)

<script>
        // 时间戳版
        function throttle(callback, time) {
            var t = 0; // 定义一个时间戳
            return function () {
                var nowDate = Date.now(); //获取当前时间戳
                console.log(nowDate)
                var args = arguments;
                var self = this;
                if (Date.now() - t >= time) {
                    callback.apply(self, args);
                    t = Date.now();
                }
            }
        }
</script>

使用方法:

text.onmousemove = throttle(count, 1000);

效果如下

  

时间戳版的意思是在持续触发事件的过程中,函数会立即执行,并且每 1s 执行一次。(在移出触发事件后,函数还会再执行一次。)

函数防抖合并插件版

// helpers.js
/**
 * 函数防抖
 * @param {Function} callback 回调函数
 * @param {Number} time 延迟的时间
 * @param {Boolean} immediate 是否立即执行
 */
this.myPlugin.debounce = function (callback, time, immediate) {
    // 设置默认值(如果用户未传参数immediate的情况下)
    if (immediate === undefined) {
        immediate = true;
    }
    var timer;                     // 定义一个定时器
    if (immediate) {
        return function () {
            clearTimeout(timer);   // 直接清楚之前的定时器
            var self = this;       // 保存this的值
            var args = arguments;  // 利用闭包保存参数数组
            var callNow = !timer;  // 取反
            timer = setTimeout(function () {
                timer = null;      // 清空定时器
            }, time)
            if (callNow) {
                callback.apply(self, args);  //调用apply进行参数的传入
            }
        }
    } else {
        return function () {
            clearTimeout(timer);   // 直接清除之前的定时器
            var self = this;       // 保存this的值
            var args = arguments;  // 利用闭包保存参数数组
            timer = setTimeout(function () {
                callback.apply(self, args);  // 调用apply进行参数的传入
            }, time);
        }
    }
}

函数节流合并插件版

// helpers.js
/**
 * 函数节流
 * @param {Function} callback 回调函数
 * @param {Number} time 延迟的时间
 * @param {Boolean} immediate 是否立即执行
 */
this.myPlugin.throttle = function (callback, time, immediate) {
    if (immediate === undefined) {// 设置默认值(如果用户未传参数immediate的情况下)
        immediate = true;
    }
    if (immediate) {
        var t;                     // 定义一个时间戳,默认为null
        return function () {
            var self = this;       // 保存this的值
            var args = arguments;  // 利用闭包保存参数数组
            // 只要时间没有值就可以执行函数 或 距离上次执行的时间已超过规定的值
            // 当前时间戳 - 之前的时间戳 ≥ 传入的时间
            if (!t || Date.now() - t >= time) {
                callback.apply(self, args);
                t = Date.now();
            }
        }
    } else {
        var timer;
        return function () {
            if (timer) {
                return;// 如果有计时器的情况下直接返回
            }
            var self = this;       // 保存this的值
            var args = arguments;  // 利用闭包保存参数数组
            timer = setTimeout(function () {
                callback.apply(self, args);  // 调用apply进行参数的传入
                timer = null;      // 函数节流要清空定时器,如果这里不清空,他会发现上面一直有定时器(return那里),就不会再次运行了
            }, time)
        }
    }
}

插件这样使用:

<!--插件要考虑通用性,易用性,尽量不要与其他功能冲突,防止污染太多的window上的全局变量,因此我这里使用多个js文件只污染一个全局变量的方式!在helpers.js中添加如下代码
if (!this.myPlugin) {
    this.myPlugin = {};
}
-->

<script src="../../plugin/helpers.js"></script>  <!--引入插件-->
<script>
        var handle = myPlugin.debounce(function (width) {  // 调用插件
            console.log(width);                            // 打印浏览器视口宽度
        }, 1000);                                          // 每隔1000毫秒打印一次
        window.onresize = function () {
            handle(document.documentElement.clientWidth);  // 浏览器窗口改变时触发
       }
</script>

结语

  • 怀着瑟瑟发抖的心情发了第一篇知识博客,有哪儿写错的请各位大牛指出。

  • 好想进入小白之列,与大牛肩并脚。

js 函数的防抖(debounce)与节流(throttle) 带 插件完整解析版 [helpers.js]的更多相关文章

  1. js 函数对象的继承 inherit 带 插件完整解析版[helpers.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS的对象继承方法 需求分析: 1. ...

  2. js 函数的防抖(debounce)与节流(throttle)

    原文:函数防抖和节流: 序言: 我们在平时开发的时候,会有很多场景会频繁触发事件,比如说搜索框实时发请求,onmousemove, resize, onscroll等等,有些时候,我们并不能或者不想频 ...

  3. 防抖debounce和节流throttle

    大纲 一.出现缘由 二.什么是防抖debounce和节流throttle 三.应用场景 3.1防抖 3.2节流 一.出现缘由 前端开发中,有一部分用户行为会频繁触发事件,而对于DOM操作,资源加载等耗 ...

  4. js 实现对象的混合与克隆效果,带完整版解析代码[helpers.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写淘宝无缝轮播图效果 对象混合 ...

  5. Java版的防抖(debounce)和节流(throttle)

    概念 防抖(debounce) 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时. 防抖,即如果短时间内大量触发同一事件,都会 ...

  6. js 防抖 debounce 与 节流 throttle

    debounce(防抖) 与 throttle(节流) 主要是用于用户交互处理过程中的性能优化.都是为了避免在短时间内重复触发(比如scrollTop等导致的回流.http请求等)导致的资源浪费问题. ...

  7. 防抖(Debounce)与节流( throttle)区别

    http://www.cnblogs.com/ShadowLoki/p/3712048.html http://blog.csdn.net/tina_ttl/article/details/51830 ...

  8. JavaScript 防抖(debounce)和节流(throttle)

    防抖函数 触发高频事件后,n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间 /** * * @param {*} fn :callback function * @param {* ...

  9. C#.Net下的防抖-Debounce和节流阀-Throttle功能实现

    C#下的防抖-Debounce.节流阀-Throttle功能实现 防抖-Debounce 连续的多次调用,只有在调用停止之后的一段时间内不再调用,然后才执行一次处理过程. 节流阀-Throttle 连 ...

随机推荐

  1. Girls' research(马拉车算法) hdu 3294

    文章目录 思路如下 Manachar代码注释 题解如下 Problem Description One day, sailormoon girls are so delighted that they ...

  2. Java 添加、读取和删除 Excel 批注

    批注是一种富文本注释,常用于为指定的Excel单元格添加提示或附加信息. Free Spire.XLS for Java 为开发人员免费提供了在Java应用程序中对Excel文件添加和操作批注的功能. ...

  3. Apache本地服务器搭建(Mac版)

    由于Mac自带apache服务器,所以无需下载,apache默认处于开启状态. 可以在浏览器输入localhost,显示It works!,代表目前处于开启状态,默认文件目录为/Library/Web ...

  4. es6声明一个类

    js语言的传统方式是通过定义构造函数,生成心得对象.是一种基于原型的面向对象系统.在es6中增加了class类的概念,可以使用class关键字来声明一个类.之后用这个类来实例化对象. 构造函数示例 c ...

  5. CSS躬行记(4)——浮动形状

    CSS规范新增了一个模块:CSS Shapes,shape-outside属性属于该模块,它能影响浮动元素周边内容流的形状(即浮动形状),可接收三类值:形状盒子.函数和图像. 一.形状盒子 形状盒子( ...

  6. Adb adb push (remote write failed: No space left on device)

    修改完成程序后, mm 后, 准备要push 进到公司测试手机里面的.之前还真的没有遇到过这个问题,查了一下, 应该是手机没空间了的 sudo adb root sudo adb remount su ...

  7. Ceph学习笔记(4)- OSD

    前言 OSD是一个抽象的概念,对应一个本地块设备(一块盘或一个raid组) 传统NAS和SAN存储是赋予底层物理磁盘一些CPU.内存等,使其成为一个对象存储设备(OSD),可以独立进行磁盘空间分配.I ...

  8. SIM900A 通过RS232串口进行短信的发送。

    一.基本数据 1.SIM900A模块支持RS232串口和LVTTL串口.保留了232口,在学习或者开发时可以监听51低端单片机和模块指令执行情况,能更快的找出原因,节省开发和学习的时间. 2.此模块供 ...

  9. pgsql中的行锁

    pgsql中的行锁 前言 用户可见的锁 regular Lock 行级别 FOR UPDATE FOR NO KEY UPDATE FOR SHARE FOR KEY SHARE 测试下加锁之后的数据 ...

  10. SpringBoot系列(六)集成thymeleaf详解版

    SpringBoot系列(六)集成thymeleaf详解版 1. thymeleaf简介  1. Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎.  2. Thymeleaf ...