回调函数中为何无法引用上层函数的变量?
发布于 11 年前 作者 chapgaga 8705 次预览 最后一次回复是 11 年前 来自 问答
var fs=require('fs');
var path=['c:/', 'd:/', ''];
for (var i = 0; i < path.length; i++) {
if (path[i].length > 0) {
// 可以得到值
console.info(path[i]);
fs.exists(path[i], function(exists) {
if (exists) {
// 为何得到的是undefined?如何将下面的变量正确输出呢?
console.info('get path inside', path[i]);
} else {
console.error('path not exists');
}
})
}
}
输出怎么是undefined?
14 回复
bind 进去就好了
异步,闭包
@hingsir 闭包上层context里面的变量,不能被闭包直接使用么? 其他语言好像是行的
@chapgaga
JavaSript可以使用调用这个闭包函数时的Context中的变量。否则,闭包中引用了
path[i],如果path === undefined,会报错的。你的示例代码中出现的这种现象,归根结底是因为把循环和异步调用函数结合在一起使用。由于
fs.exists()是一个异步函数,所以它只会在真正被调用时再去查看Context中的变量取值。此时,循环已经执行完毕,变量的取值分别是i = 3; path[3] = undefined;。因此,返回一个path not existed就是理所当然。i = 3Array.map()取代for循环Array.map(),可以用Async等模块控制调用异步函数的流程。var path=['c:/’, 'd:/’, ‘’];我怎么觉得你这标点符号是错的很明显这里形成了一个闭包,由于回调函数是异步的,在执行回调函数时其所在的上层作用域已经执行完退出了,但是由于闭包的原因,回调函数仍然引用了上层作用域 的变量对象,但此时变量的值已经改变,在这里就是i=3,所以输出undefined,此时我们可以在循环内部开辟一个执行作用域,把包含回调函数的方法放入这个作用域中,,这样就进行了作用域隔离,可以避免这个问题,因此可以这样修改:
内部是异步的,等你内部使用时,外部循环已经结束了(即i=3了),这时访问肯定是undefiend,转换成函数或使用async库
你遇到了经典错误!
@cwallow caolan, async作者名字看起来像是个中国人,呵呵
@hpgt 没错的
@cwallow 回调关系多的话,要用好多bind啊,这就是node让人头疼的地方吧?
4楼给出了说明 … 6楼已经给出了答案 . 结贴吧.
强迫症了, LZ 看一下现在帖子的内容, 插入代码 用
```@fish 额,我的帖子好像被人编辑过了:)