丸子菜端讲闭包是个啥玩意儿~

326 阅读3分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。

和我一样的小菜端看过来,大佬移步绕行吧em~,若有不足之处欢迎点评,但请嘴下留情 大家好~,我是丸子,我原本只是一个不想努力的小菜端(简称丸子菜端),一直在吃自己的老本,一直在做业务,就最近吧~,就看掘金看的,呦~ 嚯~ 这人写的真好👍,嘶~ 懂的这么多🐂🍺,查查这是个啥。大家给我卷起来了,就觉得不行啊,再不学习就出局了,年轻人的活力呢🤓,于是我就下定决心,温故而知新。奥利给~

Let's get to the point(咱进入主题吧)

我们从三个方向展开

graph TD
闭包是什么 --> 闭包的作用--> 闭包的注意点

1、闭包是个撒?

咱们就先举个🌰吧,看看代码

var closure = "闭包变量" //局部变量
function fn(){//这里的fn是一个函数
    console.log(closure)//在函数里面能访问到外部变量
}

上面有一个局部的变量closure,一个函数fn,在fn函数可以访问到closure变量。就是一个闭包,意思就是:函数的内部能访问到其他函数的变量是一个闭包
有人会说,咦,你的闭包怎么和我见过的不一样,我见的是return了一个函数出去的, 对,就下面这样的😉

function fn1(){
  var i = 1 //变量i
  return function fn2(){
     i++
     return i
  }
}
var funct = fn1()
funct()

在上面例子中有一个fn1的函数,内部有一个fn2的函数,这里面的闭包就是fn2和变量i组成的闭包。 可是为什么要一个函数套着一个函数?
因为需要局部变量,如果不用fn1函数套着,那么变量i就成为了一个全局变量,就不是使用闭包了。 函数嵌套一个函数仅仅是为了创造一个局部的变量,和形成一个闭包没有关系,但也算是闭包的一个前提吧先创建局部变量

为什么要fn2 return出去呢?
因为需要在外部访问到fn2这个函数,如果不return抛出去就无法使用,如果赋值给window上也可以访问到,所以return也仅仅是为了外部能到得到访问

2、闭包的作用是撒尼?

有两个作用:
1、能够读取函数内部的变量
2、能到让变量一直保持在内存中

function fn1(){
    var i = 1;
    newfn=function(){i+=1}
    function fn2(){
      alert(i);
    }
    return fn2;
  }
  var resolve=fn1();
  resolve(); // 1
  newfn();
  resolve(); // 2

在上面的代码里,出现的闭包就是fn2,它运行了两次,第一次是1,第二次是2,因为fn1的局部变量一直存在内存中,并没有在被调用完清除。
为什么没有被清除,因为fn1是fn2的父亲函数,最后return出去了fn2,把return出去的fn2赋值给了一个全局变量,所以fn2依赖于fn1。
在执行第一次resolve()输出的是1,后续又调用了newfn()这个函数,特别要注意newfn=function(){i+=1}这一行,这是一个全局变量,因为前面并没有用var声明,所以在外部可以直接进行操作。调用了newfn()这个匿名函数后,i变量发生了变化,变2后又执行了fn2函数被return出去,所以resolve()第二次调用是2。

3、闭包注意撒子?

在我们面试的时候一问题闭包的缺点,大部分说的就是内存泄露,可是有的人或许不知道内存泄露是什么,内存泄露是值用不到的变量,依然占据内存空间,不能被再次利用。很多时候闭包里面的变量就是我们需要的变量,但是在使用闭包的同时函数的变量会被存到内存中,内存消耗会很大,在IE中会出现内存泄露,回收不了闭包里面的变量,解决方法就是在退出函数前,把不使用的函数局部变量删除