我有一个for-loop
,其中包含一些在循环中声明的局部变量n
。因此,我预计一旦程序退出循环,n
的值就会被销毁。
但是,似乎n
的值在 for 循环之外仍然可用。为什么?另外,我应该在什么时候期望n (also the value k if uncommented)
的价值被销毁?
const delayHelper = require('./delayExecutor')
async function main() {
let promises = [];
let records = [1, 2, 3, 4];
for(let i = 0; i < records.length; i++) {
let n = 1000 + records[i];
// let k = 123;
promises.push(delayHelper.delayResolve(() => records[i], 1000).then(data => data + n))
}
console.log(await Promise.all(promises)); //print: [ 1002, 1004, 1006, 1008 ]
}
main()
//delayExecutor.js
let delayedResolve = (fun, ms) => {
return new Promise((y, n) => {
setTimeout(() => {
y(fun());
}, ms);
});
};
exports.delayResolve = delayedResolve;
这里有几个概念需要注意。1.关闭范围, 2.块范围
当您访问内部函数定义中的n
时,该变量在该内部函数的闭包范围内保持活动状态,直到不再需要它,
使用let
声明n
将在块作用域(此处for
循环(中创建一个新变量,该变量将在相应的迭代中锁定到内部函数。
您可以尝试的另一件事是使用var
声明n
这将产生不同的结果 -[1005,1006,1007,1008]
。这是因为var
不是块范围的声明,因此它不会为循环的每次迭代创建新变量。循环结束时n
的最终值1004
,该值将在逻辑data => data + n
中使用对于您问题的第二部分 - 据我所知,所有变量引用都将在函数结束时清除。由于您的 n 被锁定在内部函数的 Closure 作用域中data => data = n
因此一旦执行,n
值将被清除。
您是如何发现可以从厕所外访问n
的?我执行了您的代码并尝试访问n
超大的循环。我得到n 是未定义的错误。这完全是意料之中的。
现在,垃圾回收器决定何时需要对未使用的内存进行垃圾回收。您可以搜索V8 垃圾回收器。
有了Promise.all
承诺将并行处理,结果将解决(或拒绝(
let delayedResolve = (fun, ms) => {
return new Promise((y, n) => {
setTimeout(() => {
y(fun());
}, ms);
});
};
Promise.all([1, 2, 3, 4].map(async item=>await delayedResolve(()=> item, 1000)+1000+item))
.then(results=>console.log(results));
代码将首先处理每个承诺,然后显示所有结果。 如果你寻找顺序过程,你需要承诺链。