(包懂)JS通俗易懂的理解闭包

JS通俗易懂的理解闭包

本文章举了3个生动形象的故事来比喻闭包,即使你是JS新手,你也可以弄清楚闭包!

初步了解概念

首先,这是一个函数对吧?

var fun = function(){
    
}

现在,我们往里面添加几个变量

var fun = function(){
    var a = 1
    var b = 2
    var c = 3
}

然后,我们执行这个函数

var fun = function(){
    var a = 1
    var b = 2
    var c = 3
}
fun()

好的,现在我要提出一个问题了:当fun()运行之后,里面的a、b、c变量还存在吗?

答案是否定的,在函数执行完毕后,里面这些变量就会被销毁掉,因为这些变量没有任何必要存在了,对吧,所以他们理所应当被内存管理机制给销毁了。

好,明白了“垃圾销毁机制”后,我们继续,我们往刚才的函数中再放入一个子函数,我们将这个子函数称之为“内部函数”,而刚才的函数我们便可以称之为“外部函数”:

var fun = function(){
    var a = 1
    var b = 2
    var c = 3
    var d = function(){
        
    }
}
fun()

一切很正常,对吧,那么现在我们在这个“内部函数”里面引用一下c这个变量:

var fun = function(){
    var a = 1
    var b = 2
    var c = 3
    var d = function(){
        console.log(c)
    }
}
fun()

一切仍然很正常,直到这一步,我们将这个“内部函数”,通过return返回出去,并且用一个变量来引用保存这个返回出去的“内部函数”:

var fun = function(){
    var a = 1
    var b = 2
    var c = 3
    var d = function(){
        console.log(c)
    }
    return d
}
var s = fun()

而现在,闭包就真正的诞生了!前面我们说过,函数在执行完毕之后就会将里面所有变量都销毁,但是这是有例外的,被return出去的“内部函数”被引用了,因为外面引用了return出去的变量,你可以看到我们用一个名为s的变量保存了“内部函数”这个返回,这样保证了“内部函数”被引用,从而使其不会被“垃圾销毁机制”所销毁,因为它被引用了,所以它有作用,所以它不是垃圾,所有它不会被销毁,而最关键的是这个“内部函数”里面还引用了c这个变量,所以c也跟着变成了有作用的变量,也不会被销毁,所以,闭包=这个“内部函数”(或者也可以理解为闭包=这个“内部函数”的内在环境),所以,闭包的作用是使得变量不被销毁,且闭包环境是一个封闭的作用域

通俗易懂的例子

无论能不能理解上面的概念,没关系,下面有3个通俗易懂的例子,全部看完,你肯定可以理解!

例子1

我们把外部函数想象成一座垃圾处理厂,里面有很多垃圾,而垃圾就是变量,原本垃圾处理厂会将这些垃圾销毁,而我,也就是内部函数,我不顾危险冲进垃圾堆里挑选了一个垃圾,然后拿着走出了垃圾处理厂,现在,只要我不出意外,这个垃圾就会一直跟随着我,这个垃圾也不会被销毁,除非我死了,垃圾掉落在了地上,那么最终才会被回收销毁。

概念对应的比喻
外部函数垃圾处理厂
内部函数/闭包
被引用的变量被选中的垃圾
内部函数去到外部的方式走出去

例子2

假设外部函数是一个死刑监狱,在死刑监狱中,所有犯人都是死刑,而我也是其中一员,并且我与其中一个犯人是生死之交,即使他是残疾人,我也必须救他,于是我经过不断努力终于救出了他,并且通过挖地道逃出了监狱,但是由于他是残疾人,如果我被抓了,他也会立即被抓,毕竟现在所有警察都在找我们,而一旦被抓的后果就是死刑!所以我与他必须小心翼翼的苟活着,我不能死!我想,如果我死了,他也就死了。

概念对应的比喻
外部函数死刑监狱
内部函数/闭包
被引用的变量残疾人兄弟
内部函数去到外部的方式挖地道逃出

例子3

假设外部函数是一座满是丧尸的城市,在城市中,有许多幸存者,这些幸存者就是变量,而我是其中一员,只不过,我是一个婴儿!我的父母不知去向,我一个人在家里,岌岌可危,但就在这时,内部函数出现了,他是一名英雄,他准备带着我逃出这座城市,但糟糕的是,这座城市四面环海,没有任何陆地通往外面!可恶!我们只能无助的在海边不断寻找,天啊,我们居然找到了一支小船,这支小船就是return,太好了,我们乘上这支小船,然后在海上漂流,幸运的是,我们最终到达了一个荒岛,在这个荒岛上,我们最终幸存了下来,并且没有任何的丧尸和威胁,我们安全了!但是由于我只是一个婴儿,所以英雄不能死,一旦英雄死了,我作为一个婴儿必须也存活不下去。

概念对应的比喻
外部函数满是丧尸的城市
内部函数/闭包英雄
被引用的变量我(婴儿)
内部函数去到外部的方式坐船

标准的理解

最后,我们有必要看下标准的解释和代码示例,以便更准确的理解闭包:

  1. 闭包是什么?

闭包是指内部函数捕获并持有外部函数作用域中的变量,使得这些变量在外部函数执行完毕后仍然可以被内部函数访问。

  1. 闭包的作用是什么?

闭包的作用是:使得原本会被销毁的变量可以被内部函数所引用而不被销毁。

  1. 闭包的简单示例?

第一个例子:

var fun = function(){
    var a = 1
    var b = 2
    var c = 3
    var d = function(){
        console.log(c)
    }
    return d
}
var s = fun()
// s就是闭包

第二个例子:

var btns = document.querySelectorAll(".btn")
for (var i = 0; i < btns.length; i++) {
  (function (index){
      btns[index].addEventListener('click',function (e){
          console.log(index)
      })
  })(i)
}
/*
  在这个例子中:
  1. “外部函数”是立即调用函数;
  2. “内部函数”是事件的回调函数;
  3. “被引用的变量”是index;
  4. 没有return,但是“内部函数”作为事件监听器的回调函数,也就是被引用了,所以相当于return出去了。

  这个例子是非常常见的用于解决for遍历和事件绑定结合时索引(index)总是相同的问题,因为如果不使用闭包解决的话,index的作用域永远都是在同一个,这将导致每个回调函数拿到的index都是同一个,所以在这个例子中使用闭包来分割作用域,使得每一个index都在单独的闭包中,也就是独立且封闭的作用域中。
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值