闭包再深入

2017-08-30  本文已影响0人  hellowade

一直对闭包这个概念模糊不清,今天捣鼓半天,大致理通了。
闭包是什么?

有权访问另外一个函数作用域中的变量的函数。

一般来讲,作用域是由函数创建的(这里我们只讨论函数作用域,不涉及ES6之后的块级作用域)。每个函数的作用域都是封闭的,外部是无法访问函数作用域中的变量。
那有没有办法可以从外部访问到函数内部的变量呢
答案是有的,通过嵌套函数的方式,见下面的示例。

function change(){
    var a = 1
    function plus(){
        a++
        console.log(a)
    }
    return plus
}
var final = change()
final() //2
final() //3
final() //4

在该例中,我们得增加点知识点:

plus函数作用域内没有变量a,依据作用域链,找到父作用域中的变量a,当执行final()时,a++,a=2。再执行final()时,结果依然+1。
这里有点困惑,变量的生命周期起始于函数执行时,终止于函数执行完毕,为什么这里面函数中的变量a未被回收,数值一直递增。
原因在于变量a被函数plus引用,final()间接引用着变量a。导致变量a未被内存回收。
闭包最大的用处在于:暴露局部变量,保持变量在内存中不被回收。
再来看些经典的闭包题来理解下思路

for(var i = 1; i< 10; i++){
    function a(){
    console.log(i)
    }
} 
a() //10

为什么得到10,很简单。for循环中是函数表达式,当循环结束后,执行a(),其中的i不存在按作用域链找到上一级的i并引用,结果为10。
怎么让其按我们设想的0,1,2...输出呢?
也很简单,每次循环执行一次函数,传参,var a = i ,运用立即执行函数,见下

for(var i = 1; i< 10; i++){
    !function a(a){
    console.log(a)
    }(i)
} 

如果纠结0~9,和输出来为什么是10,可以参考下for循环的执行次序

上一篇下一篇

猜你喜欢

热点阅读