Nodejs 学习笔记之循环与闭包
来源:互联网 发布:施工组织设计编制软件 编辑:程序博客网 时间:2024/05/20 03:08
首先,来看一段代码(来自《nodejs开发指南》)
for( var i = 0;i<files.length;i++){ fs.readFile(files[i],'utf-8',function (err,contents) { console.log(files[i] + ':' + contents); })}
结果是
undefined:AAAundefined:BBBundefined:CCC
输出 undefined 是因为 fs.readFile是一个异步方法,它的回调在for循环执行完毕后才开始执行, 而此时变量 i=files.length, 超出了边界。如果我们打印出i,发现i的值一直都是3。那么如何解决这个问题呢?我们手动创建一个闭包,如下:
varfs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
for (vari =0; i < files.length; i++) {
(function(i) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files[i] + ': ' + contents);
});
})(i);
}
输出如下:
a.txt: AAA
c.txt: CCC
b.txt: BBB
上述方法,解决了undefined的问题,但是显然可读性较差 ,因此建议将for循环写成如下方式:
files.forEach(function (filename) { fs.readFile(filename,'utf-8',function (err,contents) { console.log(filename+':'+contents); })})
上述例子中涉及到了闭包的问题,那么什么是闭包呢?
通俗地讲, JavaScript 中每个的函数都是一个闭包,但通常意义上嵌套的函数更能够体
现出闭包的特性,请看下面这个例子:
var generateClosure = function() {
var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter = generateClosure();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2
console.log(counter()); // 输出 3
这段代码中, generateClosure() 函数中有一个局部变量count, 初值为 0。还有一
个叫做 get 的函数, get 将其父作用域,也就是 generateClosure() 函数中的 count 变
量增加 1,并返回 count 的值。 generateClosure() 的返回值是 get 函数。在外部我们
通过 counter 变量调用了 generateClosure() 函数并获取了它的返回值,也就是 get 函
数,接下来反复调用几次 counter(),我们发现每次返回的值都递增了 1。
让我们看看上面的例子有什么特点,按照通常命令式编程思维的理解, count 是
generateClosure 函数内部的变量,它的生命周期就是 generateClosure 被调用的时
期,当 generateClosure 从调用栈中返回时, count 变量申请的空间也就被释放。问题
是,在 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 分别调用了 generateClosure() 函数,生成了两个闭包的实例,它们内部引用的 count 变量分别属于各自的
运行环境。我们可以理解为,在 generateClosure() 返回 get 函数时,私下将 get 可
能引用到的 generateClosure() 函数的内部变量(也就是 count 变量)也返回了,并
在内存中生成了一个副本,之后 generateClosure() 返回的函数的两个实例 counter1
和 counter2 就是相互独立的了。
更多解释可以参照: https://wenku.baidu.com/view/f5367cc2bb4cf7ec4afed009.html
- Nodejs 学习笔记之循环与闭包
- nodejs事件循环学习笔记
- 【学习笔记】nodejs之包管理npm/yarn
- nodejs学习笔记(三)——javascript的回调与nodejs的事件循环
- nodejs学习笔记二:闭包和异步编程
- Nodejs学习笔记之express
- nodejs学习笔记 之prototype
- Groovy学习笔记之块、闭包与函数
- JavaScript学习笔记之函数表达式与闭包
- 关于for循环与闭包的一点点点笔记
- nodejs学习笔记一 nodejs简介与安装
- nodejs+nginx+mongdb+redis安装学习笔记(之nodejs安装)
- 学习笔记之NodeJs基本操作
- NodeJS学习笔记之Http模块
- NodeJS学习笔记之FS文件模块
- NodeJS学习笔记之FS文件模块
- Nodejs学习笔记之NET模块
- nodejs之koa学习笔记(1)
- jar包添加到本地maven库
- jvm cpu100% 问题分析
- Read-only file system
- [模式分类] Parzen窗概率密度估计与Kn近邻概率密度估计
- 47、java常用类-DateFormat
- Nodejs 学习笔记之循环与闭包
- 高版本cad文件打不开可以使用迅捷CAD转换器
- linux思维导图独立整理归纳
- Merge Two Binary Trees
- Java集合 Json集合之间的转换
- servlet工作原理(乱码情况)
- 48、java常用类-Calendar
- linux ehci ehci_urb_enqueue之qh_urb_transaction()分析 【史上最强大分析】
- 针对通过 SSH 连接到 Azure Linux VM 时发生的失败、错误或被拒绝问题进行故障排除