Page 159 - Node.js开发指南
P. 159
152 附录 A JavaScript 的高级特性
是,在 generateClosure() 调用结束后,counter() 却引用了“已经释放了的” count
变量,而且非但没有出错,反而每次调用 counter() 时还修改并返回了 count。这是怎
么回事呢?
这正是所谓闭包的特性。当一个函数返回它内部定义的一个函数时,就产生了一个闭包,
闭包不但包括被返回的函数,还包括这个函数的定义环境。上面例子中,当函数
generateClosure() 的内部函数 get 被一个外部变量 counter 引用时,counter 和
generateClosure() 的局部变量就是一个闭包。如果还不够清晰,下面这个例子可以帮助
你理解:
var generateClosure = function() {
var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter1 = generateClosure();
var counter2 = generateClosure();
console.log(counter1()); // 输出 1
console.log(counter2()); // 输出 1
console.log(counter1()); // 输出 2
console.log(counter1()); // 输出 3
console.log(counter2()); // 输出 2
上面这个例子解释了闭包是如何产生的:counter1 和 counter2 分别调用了 generate-
Closure() 函数,生成了两个闭包的实例,它们内部引用的 count 变量分别属于各自的
运行环境。我们可以理解为,在 generateClosure() 返回 get 函数时,私下将 get 可
能引用到的 generateClosure() 函数的内部变量(也就是 count 变量)也返回了,并
在内存中生成了一个副本,之后 generateClosure() 返回的函数的两个实例 counter1
和 counter2 就是相互独立的了。
A.2.2 闭包的用途
1. 嵌套的回调函数
闭包有两个主要用途,一是实现嵌套的回调函数,二是隐藏对象的细节。让我们先看下
面这段代码示例,了解嵌套的回调函数。如下代码是在 Node.js 中使用 MongoDB 实现一个
简单的增加用户的功能: