了解javascript闭包和内存使用情况

jco*_*der 15 javascript closures

编辑:这只是一个简单的例子来消除我对一个更大的程序的关注.我不会使用这个实际的代码:)

如果我运行这个 -

<!DOCTYPE html>
<html>
<head>
<script>

function update(amount, win, data)
{
    win.innerText = 'Count is ' + amount;
    setTimeout(function() { update(amount + 1, win, {data: 'something'})}, 1000);
}

window.onload = function() {

  var win = document.getElementById('item');    
  update(0, win, 0);
}
</script>
</head>

<body>
<div id="item"></div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

对setTimeout的调用可能会创建一个闭包,它将参数的内容捕获到"更新"函数(金额,胜利,数据).所以这些变量在内存中维护,直到调用超时并返回,以便它们在该函数调用中可用...

但是该函数为超时的下一次迭代创建了一个新的闭包......在第二个闭包中会捕获什么?它只是这些变量的副本还是在新的闭包中再次捕获构成函数调用一部分的变量?

基本上,由于每个闭包中的数据变得越来越大,这最终会耗尽内存,还是这样安全合理?

ser*_*gio 7

在我的理解中,当创建一个闭包时,当前的词汇上下文与它捆绑在一起.在你的情况下,它将是amount, win, data.

当超时触发时,将使用该上下文来执行闭包,从而再次调用该函数update; 这个调用尽管看起来可能不是递归的,因为之前update已经结束的执行及其原始上下文(动态,与词法不同)已经被释放.(我认为这一点很重要,因为看起来你担心由于递归导致的堆栈增长).

因此,再次update执行第二次并再次设置超时并创建闭包.这个闭包与当前的词法执行上下文捆绑在一起(仍然只包括amount, win, data)并与计时器一起安排.然后update完成并从堆栈中删除.然后再次调用计时器并再次调用更新...

因此,您不应该担心上下文的无限增长,原因有二:首先,只有词汇上下文与闭包捆绑在一起; 该调用实际上不是递归的.