浅谈·Javascript中的闭包

最近在学习Node.js的时候遇见了Javascript中的闭包概念,在网上翻阅了一些文章,试着自己理解总结一下。

什么是闭包?

在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

一段闭包的示例:

function outer(){
    var count = 0; //一个函数作用域内的变量
    return function inner(){ //outer函数返回一个inner函数的引用
        alter(count++); //当inner函数被调用使会弹窗count的值
    }
}
var func = outer(); //变量func持有outer函数返回的inner函数的引用
func(); //相当于调用了inner函数

上面这段代码中,inner函数就是一个“闭包”,它返回了外部函数作用域内的变量,并且自身作为外部函数的返回值。

闭包的作用

我们知道,在Javascript中有两种变量的作用域:全局变量和局部变量。

当我们需要得到一个函数作用域里局部变量的值时,我们有两种方法:

  • 一是让这个函数返回这个变量
function outer() {
    var count = 10;
    return ++count;
}
console.log(outer());
console.log(outer());

结果11 11

  • 二是使用闭包
function outer() {
    var count = 10;
    return function inner() {
        return ++count;
    }
}
var result = outer();
console.log(result());
console.log(result());

结果11 12

第一种方法在函数被调用后,局部变量就从内存中被回收了。而第二种闭包的方法,因为inner函数的引用仍被全局变量result所持有,所以它不会被回收,outer作为inner的父函数自然也就一直存于内存之中,它的局部变量也不会被回收。
但如果连续调用outer()()的话,输出的结果是不会递增的,答案很明显,没有任何变量持有inner函数(调用outer()返回inner的引用)的引用,所以它被GC回收了。

如果能正确理解JS中的作用域链的话,就可以知道闭包的作用是

为子函数提供一种可以访问父函数(父级作用域)内变量的方法

初入JS,很多概念也只是知其一不知其二

评论已关闭