前言:

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

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

本文借鉴: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. My背包九讲——概述

    文章目录 什么是背包问题 背包问题的分类 [第一讲 01背包问题](https://blog.csdn.net/qq_34261446/article/details/103705068) 第二讲 完 ...

  2. mui在vue_cli上使用

    在main.js里添加 import mui from './assets/js/mui.js' 如果不添加下面会显示mui is not defined 报错 Vue.prototype.mui = ...

  3. RHCS概述

    RHCS概述 创建RHCS集群环境 创建高可用Apache服务 1 创建RHCS集群环境 1.1 问题 准备四台KVM虚拟机,其三台作为集群节点,一台安装luci并配置iSCSI存储服务,实现如下功能 ...

  4. 用最新的版本,蹦最野的迪~~~IDE写大数据程序避坑指南

    文章更新于:2020-04-05 注:本次实验使用的操作系统及各个程序版本号 类别 版本号 说明 操作系统 Ubuntu 16.04.6 LTS 代号 xenial jdk java version ...

  5. webstorm 永久激活方法

    打开终端,执行: cd /etc/ sudo vim hosts 在最后一行加上: 0.0.0.0 account.jetbrains.com 打开webstorm,选择Activation Code ...

  6. Android 图片裁剪库 uCrop

    引语 晚上好,我是猫咪,我的公众号「程序媛猫咪」会推荐 GitHub 上好玩的项目,挖掘开源的价值,欢迎关注我. 现在 Android 开发,离不开图片,必然也需要图片裁剪功能,这个实现可以调用系统的 ...

  7. C++值多态:传统多态与类型擦除之间

    引言 我有一个显示屏模块: 模块上有一个128*64的单色显示屏,一个单片机(B)控制它显示的内容.单片机的I²C总线通过四边上的排针排母连接到其他单片机(A)上,A给B发送指令,B绘图. B可以向屏 ...

  8. 34 io流-- 打印流和对象流

    概述 io流分为字符流和字节流,具体分类相见下图 字符流:char 一些基本文本的数据传输 字节流:byte 图片.视频等用文本查看器查看不了的文件都是二进制文件,只能用字节流传输,使用字符流cp的看 ...

  9. SQL基础系列(1)-基本语法--转载w3school

    1.    建原始表 USE [Northwind] GO /****** Object:  Table [dbo].[Persons]    Script Date: 2016/6/8 7:31:5 ...

  10. GitHub搭建个人主页

    GitHub搭建个人主页 1.注册登录GitHub 2.新建仓库 新建一个名为"username.github.io",其中username为你的用户名,仓库必须为公有类型,私有仓 ...