美文网首页
JavaScript 闭包的深入探索

JavaScript 闭包的深入探索

作者: yancy_1012 | 来源:发表于2020-07-25 17:58 被阅读0次

哈哈,终于又能让大家看到我的文章了,开心😊。感觉又有好长时间没写了,各位看官,请跟随我一起畅游知识的海洋吧。

上次跟大家分享了 JavaScript作用域 的相关知识点,也不知道大家看下去多少,那可是基础中的基础,学习就是这样,只有基础牢固了,接收其他知识的时候才能如鱼得水,如胶似漆,如梦如幻,如……………………

(请原谅作者语文知识的欠缺)

今天主要是跟大家分享一下javascript中闭包的问题,如你所料,又是一篇基础分享,赶紧止住这些呼之欲出的废话,开始我们的表演 ↓↓↓↓

1.什么是闭包

在我们看到的各种技术书籍中,都会把闭包描述的很抽象,这里我们先给闭包一个定义 闭包就是可以在函数外部访问函数作用域中的的内部变量,同时它也可以将变量长久的保存在内存中 。在javascript中,闭包是一个重难点,是因为它确实很难理解,重要是因为在javascript中很多高级写法都需要闭包来实现。

先来个开胃小栗子吧。

1.1 调用函数,实现每次+1的输出操作。


function a () {

  let number = 10;

  number++;

  console.log(number);

}

a() // 11

a() // 11

a() // 11

上述代码中,并不能实现我们所需要的效果。这是为什么呢?

因为函数a在执行完成后,就会将内部变量number释放掉。每次执行a函数都会重新创建执行 变量创建 -- 使用 -- 销毁 的整个过程,所以函数调用会一直输出同一个结果。那么如何才能达到题目的要求?

改进版


function a () {

  let number = 10;

  return function () {

    number++;

    console.log(number)

  }

}

let result = a()

result(); // 11

result(); // 12

result(); // 13

通过改进,已经实现了题目所要求的效果。

这里是因为执行a之后,还存在number变量的引用,会将变量长久的保存在内存中,不会释放掉。所以可以实现依次累加的效果。

1.2 实现下列代码从 0-9 打印输出

问题


for(var i = 0;i < 10 ; i ++) {

setTimeout(function () {

    console.log(i)

  }, 0);

}

// 输出10个10

问题剖析:

  1. setTimeout是异步执行的,(这里与JavaScript事件队列相关,后续会出相关文章。)。等到循环执行完成之后才会执行打印函数。

  2. var定义的是全局变量,i++修改的也是全局变量

  3. 在打印函数执行的时候,i 的值已经为10。所以打印函数打印的都是10

改进


for(var i = 0;i < 10 ; i ++) {

  function a(i){

    return function (){

      console.log(i)

    }

  }

setTimeout(a(i), 0);

}

解决方法剖析:

  1. 由于setTimtout执行的是闭包函数,每次传递到 a 函数中的 i 值都会被保存,所以打印函数打印的是自己保存的 i

相信你看到这里已经累了。先休息下吧,眺望一下远方,舒缓一下眼睛。如果你是在车上,请闭上双眼休息一下。


2.闭包的用途

2.1 使用闭包实现 setTimeout 传参

形如这种方式使用,我们可以用闭包实现 setTimeout 传参的效果


for(var i = 0;i < 10 ; i ++) {

  function a(i){

    return function (){

      console.log(i)

    }

  }

setTimeout(a(i), 0);

}

2.2 函数防抖和节流

这里只通过实例代码让大家看下,后期会出文章说明。

函数防抖实现


function debounce(fn) {

  let timeout = null;

  return function () {

    clearTimeout(timeout);

    timeout = setTimeout(() => {

      fn.apply(this, arguments);

    }, 500);

  };

}

函数节流实现


function throttle(fn) {

  let canRun = true;

  return function () {

    if (!canRun) return;

    canRun = false;

    setTimeout(() => {

      fn.apply(this, arguments);

      canRun = true;

    }, 500);

  };

}

3.使用闭包的注意点

3.1 内存泄漏问题

因为闭包会将变量长久的保存在内存中,所以会造成内存泄漏,所以需要在使用完成之后销毁变量,释放内存。

3.2 this指向问题

此问题我们在讨论this指针的时候讨论过,闭包的this是指向window的。


var obj = {

  getName: functioin() {

return function () {

      console.log(this)

    }

  }

}

obj.getName()() // window

4.实现篇

4.1 使用闭包实现一个三击响应事件

第一步,实现点击输出123


let box = document.getElementById('box')

box.onclick = (function () {

  let count = 1;

  return function () {

    console.log(count)

    count ++

  }

})()

点击 box 的元素,可以看到控制台输出123

第二步,添加时间控制,1s内连续点击三次后执行事件


let box = document.getElementById('box')

box.onclick = (function () {

  let count = 0;

  let start = Date.now() // 添加开始时间

  return function () {

    count ++

    if (count === 3) {

      let end = Date.now() // 结束时间

      if (end - start <= 1000) { // 如果三次点击事件在1s内,输出成功

        console.log('三击事件响应成功')

      }

      count = 0; // 三击之后将条件重置

      start = Date.now() // 开始时间为当前时间

    }

  }

})()

第三步,友情提示

将下方代码修改之后,可由三击事件变为任意多击事件。


if (count === n) // n代表点击次数

好了亲爱的看官朋友们,本次分享的内容就到这里了。希望你们能在自己喜欢的道路上越走越远。🤗🤗🤗

相关文章

  • JavaScript 闭包的深入探索

    哈哈,终于又能让大家看到我的文章了,开心?。感觉又有好长时间没写了,各位看官,请跟随我一起畅游知识的海洋吧。 上次...

  • 深入理解javascript原型和闭包[目录]

    文章地址:深入理解javascript原型和闭包 文章:深入理解javascript原型和闭包 目录列表 (不能跳...

  • 深入理解javascript原型和闭包(完结)

    深入理解javascript原型和闭包(1)——一切都是对象 深入理解javascript原型和闭包(2)——函数...

  • JavaScript深入理解-闭包(Closure)

    推荐文章:学习Javascript闭包(Closure)- 阮一峰javascript深入理解-从作用域链理解闭包...

  • 深入理解javascript原型和闭包

    王福朋 - 博客园 —— 《 深入理解javascript原型和闭包》 目录:深入理解javascript原型和闭...

  • 闭包

    原文出处 JavaScript深入之闭包 定义 MDN 对闭包的定义为: 闭包是指那些能够访问自由变量的函数。 那...

  • javascript函数,以及闭包的理解

    javascript函数,以及闭包的理解 深入理解javascript函数定义与函数作用域深入理解javascri...

  • 实用网站

    JS scrollIntoView()的用法 阮一峰 闭包 null和undefined javascript深入...

  • 前端学习资料

    javascript流行框架,工具,css组件,Charting深入理解javascript原型和闭包(完结)Fl...

  • JavaScript深入之闭包

    JavaScript深入系列第八篇,介绍理论上的闭包和实践上的闭包,以及从作用域链的角度解析经典的闭包题。 定义 ...

网友评论

      本文标题:JavaScript 闭包的深入探索

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