闭包和函数和函数的环境息息相关。
下面看一个例子

/** 
1.对于函数来说,函数内部创建的变量称为局部变量(形参也是局部变量),如果声明的本地变量名和全局变量名一样,在该局部变量所处作用域有效范围内使用该变量时,本地变量的值将会覆盖掉全局变量的值。

2.不在本地作用域定义的变量称为自由变量。
如该函数是一个嵌套函数,使用了变量 test,但函数内部没有声明变量 test,而是在嵌套该函数的外部函数定义了一个变量 test,被该嵌套函数使用的变量 test,便是一个自由变量;
或本地没有定义变量 list,该变量是在最外层定义的全局变量,该变量也被称为自由变量。

3.每个函数都有自己的环境(environment)。
该环境存储了可敲定(close)该函数的所有变量(包括局部变量和自由变量,注意,只会存储函数内使用了的变量)的值。
可敲定函数的环境:有了给函数内每个自由变量都提供了值的环境后,便将函数敲定了。

4.闭包:包含自由变量的函数与为所有这些自由变量提供了变量绑定的环境一起,被称为闭包。
**/

// 全局变量test
var test = 'global'

function msg() {
    // 局部变量test
    var test = 'local'
    
    // 嵌套函数 inner,是函数都会拥有一个环境,该环境储存了与之相关联的变量
    function inner() {
        return test // 在该函数作用域内,test 的值是局部变量 test 的值 local
    }
    
    return inner // 这里不仅 return 了 inner 函数,还把inner 函数与之相关的环境也 return 出去了
 }

let fun = msg() // inner 函数的引用赋值给变量 fun 
let result = fun() // 调用 inner 函数,变量 test 会去 inner 函数相关的环境去取。值为 local

计时器例子

function count() {
   // 局部变量
   let num = 0
   
   // 该函数拥有一个可敲定函数的环境,存储了自由变量 num 
   function counter() { 
    num = num + 1
    return num
   }
   
   return counter // 返回 counter函数,这是一个闭包:包括 counter 函数的引用 + counter 函数与之相关的环境;利用该环境可以获取到自由变量 num 的值
}

let test = count() // 获取 counter 函数的引用,以及 couter 函数的环境

let result = test() // 调用 counter 函数,虽然我们无法在全局作用域中找到变量 num,但是我们拥有 counter 函数的闭包,可以从 counter 函数的环境中获取变量 num 的值。除此之外,无法通过其他当时获取到变量 num。

君额上似可跑马
39 声望4 粉丝