Page 158 - Node.js开发指南
P. 158
附录 A JavaScript 的高级特性 151
任何地方隐式定义的变量(未定义直接赋值的变量)。 1
需要格外注意的是第三点,在任何地方隐式定义的变量都会定义在全局作用域中,即不
通过 var 声明直接赋值的变量。这一点经常被人遗忘,而模块化编程的一个重要原则就是
避免使用全局变量,所以我们在任何地方都不应该隐式定义变量。
2
A.2 闭包
闭包(closure)是函数式编程中的概念,出现于 20 世纪 60 年代,最早实现闭包的语言
是 Scheme,它是 LISP 的一种方言。之后闭包特性被其他语言广泛吸纳。 3
闭包的严格定义是“由函数(环境)及其封闭的自由变量组成的集合体。”这个定义对
于大家来说有些晦涩难懂,所以让我们先通过例子和不那么严格的解释来说明什么是闭包,
然后再举例说明一些闭包的经典用途。
4
A.2.1 什么是闭包
通俗地讲,JavaScript 中每个的函数都是一个闭包,但通常意义上嵌套的函数更能够体
现出闭包的特性,请看下面这个例子: 5
var generateClosure = function() {
var count = 0;
var get = function() {
count ++; 6
return count;
};
return get;
};
7
var counter = generateClosure();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2
console.log(counter()); // 输出 3
8
这段代码中,generateClosure() 函数中有一个局部变量count,初值为 0。还有一
个叫做 get 的函数,get 将其父作用域,也就是 generateClosure() 函数中的 count 变
量增加 1,并返回 count 的值。generateClosure() 的返回值是 get 函数。在外部我们
通过 counter 变量调用了 generateClosure() 函数并获取了它的返回值,也就是 get 函 9
数,接下来反复调用几次 counter(),我们发现每次返回的值都递增了 1。
让我们看看上面的例子有什么特点,按照通常命令式编程思维的理解,count 是
generateClosure 函数内部的变量,它的生命周期就是 generateClosure 被调用的时
期,当 generateClosure 从调用栈中返回时,count 变量申请的空间也就被释放。问题 10