Roy*_*mir 10 javascript performance memory-leaks
有人问我(由朋友)建立一个计时器(每秒写一行的无限计时器),但没有setInterval.
我解决了它:
var i = 0;
function k(myId, cb)
{
setTimeout(function ()
{
console.log(myId);
cb();
}, 1000);
}
function go()
{
i++;
k(i, go);
}
go();
Run Code Online (Sandbox Code Playgroud)
它正在发挥作用.
问题是,我担心会有内存压力.它实际上创建了一个递归,并在一段时间后(一周或某事) - 该过程将消耗大量内存.(堆栈永远不会被释放)
如何更改我的代码以免耗费大量内存?
sle*_*man 13
它可能看起来像递归,但setTimeout不会创建递归.
setTimeout的工作方式是它立即返回.所以调用k立即以其堆栈释放结束.
当超时实际发生并且go再次发生调用时,它不是从上一次调用的点开始,k而是来自全局范围*.
*注意:我没有使用ECMAScript规范中定义的范围的严格含义.我的意思是调用k将被制作为就像你用普通<script></script>标签写的那样:也就是说,在任何其他函数调用之外.
在您的特定情况下,实际包含在k函数创建的闭包中的内容非常少.唯一重要的闭包是参数cb和参数myId.即便如此,它只持续大约一秒钟:
#1 function k(myId, cb) {
#2 setTimeout(function(){
#3 console.log(myId); // there is a closure here to myId
#4 cb(); // and another one for cb
#5
/* But at this point in the function, setTimeout ends
* and as the function returns, there are no remaining
* references to either "cb" or "myId" accessible
* anywhere else. Which means that the GC can immediately
* free them (though in reality the GC may run a bit later)
*/
#6 }, 1000); // So one second is roughly the longest the closure lasts
}
Run Code Online (Sandbox Code Playgroud)
我应该注意你的代码相当复杂.它可以写得更简单,如果你只是像这样编写它,根本不使用闭包(减去全局变量i):
// Simpler, does exactly the same thing:
var i = 0;
function go () {
console.log(i);
i++;
setTimeout(go, 1000); // callback
}
go();
Run Code Online (Sandbox Code Playgroud)
这一行是假的:
它实际上创建了一个递归,并在一段时间后(一周或某事) - 该过程将消耗大量内存.(堆栈永远不会被释放)
它并没有创造递归,因为该函数退出完全,然后再调用.
递归堆栈在彼此之上
function a() {a()}; // function calls itself until a stack overflow.
Run Code Online (Sandbox Code Playgroud)
堆栈看起来像这样
a()
a()
a()
a() ... until a crash.
Run Code Online (Sandbox Code Playgroud)
使用setTimeout,您可以执行一个函数.该函数设置一个事件让函数再次运行 - 但这里有一个重要的区别:函数退出,完全,并且已经消失[1].然后又被召唤了.
执行明智,它与这样做没有太大区别:
function a() {console.log("I am called");}
a(); // Call the function;
a(); // Call the function again
a(); // Call the function again
Run Code Online (Sandbox Code Playgroud)
setTimeout如果你愿意,只是给浏览器一个"呼吸"的机会.屏幕更新的机会,其他事件要处理.block浏览器使用正确的术语并不是这样.
| 归档时间: |
|
| 查看次数: |
12764 次 |
| 最近记录: |