美文网首页工作生活
函数防抖(闭包作用域)

函数防抖(闭包作用域)

作者: chenjieyi | 来源:发表于2019-07-03 17:02 被阅读0次

今天,小洁和小惠看了(实现)函数防抖的代码,本来是要解决防抖,我们却困惑为什么连续点击三次会执行三次定时器(希望不会有人像我们一样傻有这种困惑),下面是待解决的问题(看动图)及代码
(为了下面的一系列描述可以简单粗暴,我把网友的代码改编了一下)
代码(此处还没实现函数防抖)如下:

// Js
var count = 0;
// 防抖的重点在于闭包作用域和清除定时器
function debounce() {
    consoleTime("1.debounce")

    var timer; // 定时器
    clearTimeout(timer); // 清除定时器
    timer = setTimeout(function () {
        funct();
    }, 1000);
}

// 定时器要执行的函数
function funct(args) {
    consoleTime("2.定时器")
    console.log("----- 分割线 -----")

    let testId = document.getElementById("test");
    ++count;
    testId.innerHTML = `hello ${count}`;
}

// 打印时间
function consoleTime(text) {
    let date = new Date();
    console.log(text, date.toLocaleTimeString(), date.getMilliseconds());
}

// html
<button onclick="debounce()">点击</button>
待解决防抖问题.gif

敲黑板,下面进入重点了,在上述代码基础上实现函数防抖,代码如下。

业务场景:假设客户在保存表单时,然后不小心连续点击了两次保存,那么就会发送两次请求。
那么我们为了解决这个不小心连续点击发送多次请求的问题,设定1秒内不管我们点多少次,都只发送一次请求。而函数防抖就是,不管你在设定的时间内点击了多少次,只有在最后一次才执行了你的目标函数。

var count = 0;
// 防抖的重点在于闭包作用域和清除定时器
function debounce() {
    var timer; // 定时器
    // 重点
    return function () {
        consoleTime("1.闭包")

        clearTimeout(timer); // 清除定时器,重点
        timer = setTimeout(function () {
            funct();
        }, 1000);
    }
}
// 定时器要执行的函数
function funct(args) {
    consoleTime("2.定时器")
    console.log("----- 分割线 -----")

    let testId = document.getElementById("test");
    ++count;
    testId.innerHTML = `hello ${count}`;
}

// 打印时间
function consoleTime(text) {
    let date = new Date();
    console.log(text, date.toLocaleTimeString(), date.getMilliseconds());
}

// 重点:先把debounce函数返回的匿名函数(闭包)赋值给一个变量
var test = debounce()

// html, 这里看清楚了,onclick绑定的是test不是debounce
<button onclick="test()">点击</button>
实现函数防抖的点击.gif

分析:
两个知识点(闭包作用域和定时器)
1、var test = debounce()
2、return function(){...}
3、clearTimeout(timer);

实现原理:
1、需要设定在某个时间内,只执行最后一次,因此用到了定时器setTimeout 来设定时间。

2、因为只执行最后一次,所以需要在每次执行之前把上一次的清除掉,因为设定时间还没到,那么定时器里的函数还没执行,所以我们清除了上一次的定时器函数就不会执行了。因此有重点3,所以每次我们都把定时器setTimeout返回的id记录下来。

3、使用闭包,是为了在它所在的作用域保存setTimeout返回的id,以便于在设定时间内点击时清除上一次的setTimeout。

4、如果onclick绑定debounce返回的匿名函数,每一次点击,debounce都会重新执行。那么clearTimeout是清除不了上一次定时器的。

5、onclick绑定test,每次点击,test()都能访问debounce()的内部作用域,所以能记录每次定时器setTimeout返回的id,并清除上一次的定时器。(闭包所在的内部作用域变量不会被回收)

本来没打算写函数防抖的,因为网上很多文章,我写这个是为了记录学习理解的内容。写着写着不会表达了,如有错误表达望指出。

相关文章

  • 闭包实现函数防抖节流

    闭包函数的典型应用就是防抖节流函数 闭包 红宝书(p178)上对于闭包的定义: 闭包是指有权访问另外一个函数作用域...

  • 函数防抖(闭包作用域)

    今天,小洁和小惠看了(实现)函数防抖的代码,本来是要解决防抖,我们却困惑为什么连续点击三次会执行三次定时器(希望不...

  • 14.JS基础之作用域与闭包

    作用域: 全局作用域 函数作用域 块级作用域(ES6新增) 常见的闭包有:作为函数返回值的闭包与作为函数参数的闭包...

  • 作用域和闭包

    目录 概述 作用域编译过程词法作用域全局作用域函数作用域 闭包循环和闭包闭包的用途性能 总结 概述 作用域和闭包一...

  • 2018-01-07 关于javascript闭包和作用域的理解

    关于 javascript 闭包的一些思考 作用域 词法作用域 函数作用域 块作用域 闭包 什么是作用域? 作用域...

  • 如何理解闭包?

    1、定义: 嵌套在函数作用域中的函数,称为闭包函数。该作用域称为闭包环境。通过闭包函数可以访问闭包函数所在函数作用...

  • JS面试常见问题汇总

    1、闭包 什么是闭包? 闭包就是可以访问另一个函数作用域中的变量的函数。 闭包的作用域链包含着它自己的作用域,以及...

  • 作用域、作用域链、闭包、面向对象、执行上下文

    作用域 作用域链 函数的提前声明 闭包 JavaScript 闭包与类(原型链)之间的开发方式 构造函数和普通函数...

  • 内存泄漏

    闭包 在闭包中,内部函数引用外部函数变量,实际上是应用了外部函数的作用域(scope)对象 如果作用域对象所在函数...

  • 所谓闭包

    所谓闭包 Closures (闭包)是使用被作用域封闭的变量,函数,闭包等执行的一个函数的作用域。通常我们用和其相...

网友评论

    本文标题:函数防抖(闭包作用域)

    本文链接:https://www.haomeiwen.com/subject/jpzthctx.html