首页 > 代码库 > JavaScript中的闭包

JavaScript中的闭包

在介绍JavaScript的闭包前,首先需要搞清楚以下几个概念:

闭包:

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

以上是维基百科中对于闭包的定义,后面会详细解释JavaScript中是如何实现闭包的

第一类对象:

第一类对象(First-class object,第一类公民)也是计算机科学中的一个术语,指可以在执行期创造并作为参数传递给其他函数或存入一个变量的实体。一般具有以下特性:

  • 可以被存入变量或其他结构
  • 可以被作为参数传递给其他函数
  • 可以被作为函数的返回值
  • 可以在执行期创造,而无需完全在设计期全部写出
  • 即使没有被系结至某一名称,也可以存在

从这些特性我们可以知道JavaScript中的函数就是属于第一类对象,你可以像使用原始值(字符串,数字)一样使用它们。

作用域:

和大多数语言一样,JavaScript采用的是静态作用域,也被称为词法作用域。词法变量的作用域可以是一个函数或一段代码,该变量在这段代码区域内可见(visibility);在这段区域以外该变量不可见(或无法访问)。词法作用域里,取变量的值时,会检查函数定义时的文本环境,捕捉函数定义时对该变量的绑定。不过JavaScript只支持函数作用域(function scope),不支持块级作用域(block scope),例如

function test(o) {    var i = 0;                         // i 在整个函数体内均有定义    if(typeof o == "object") {        var j = 0;                     // j 在函数体内也均有定义,而不仅仅是这个if代码段内        for(var k = 0; k < 10; k++) {  // k 在函数体内也均有定义,而不仅仅是for循环内            console.log(k);            // 输出数字0~9        }        console.log(k);                // 输出10, k 已经在循环体内定义了,而且在循环结束后为赋值为10    }    console.log(j);                    // j已经被定义了,但可能没有初始化}

JavaScript中的闭包