JavaScript 内存泄漏检测
不再需要内存泄漏的内存没有返回到空闲内存池或操作系统。
在三种最常见的情况下可能会发生内存泄漏:意外全局变量
、忘记的回调或计时器
和 DOM 引用不足
。
JavaScript 中的 意外全局变量
内存泄漏
意外全局变量
未声明为全局
变量。垃圾收集器无法收集它们,从而导致内存泄漏。
name
变量被创建为全局 window.name
,它分配的空间永远不会被释放。
function fn1() {
// `name` is not declared
name = new Array(99999999)
}
fn1();
使用使用严格;
避免 JavaScript 中的内存泄漏
function fn1() {
'use strict';
name = new Array(99999999)
}
fn1();
输出:
未使用
变量未使用,需要删除或正确处理以释放内存空间。
最关键的一点是找到不再需要的内存。
JavaScript 使用垃圾收集器来确定代码的某个部分是否需要内存。
许多垃圾收集器使用 mark-and-sweep 算法。
使用"use strict";
来避免 JavaScript 中的全局变量引起的内存泄漏
在 Chrome DevTools 的 Memory
标签页上使用 heap allocations
。
你可以通过按 F12 或转到 Right Click
-> Inspect
-> Memory
在 Chrome 中打开 DevTools。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<button id="leak-button">Start</button>
<button id="stop-leak">Stop</button>
<script>
var x=[];
var running = false;
function grow(){
x.push(new Array(1000000).join('x'));
if(running)
setTimeout(grow,1000);
}
$('#leak-button').click(function(){
running = true;
grow();
});
$('#stop-button').click(function(){
running = false;
});
</script>
</body>
</html>
输出:
在这里,每当用户单击开始
按钮并将包含百万个 x
字符的字符串推送到数组中时,脚本都会将 10.000
节点附加到 DOM
。
即使在按下停止
按钮后,垂直的部分蓝线也显示内存泄漏。
变量 x
是内存泄漏的原因,因为它是一个全局变量,即使不再需要它也会占用空间。
使用 {once: true}
和 removeEventListener()
避免 JavaScript 中的 DOM 引用不足导致的内存泄漏
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<button id="trigger">Trigger</button>
<script>
var clickElement = document.getElementById("click");
const hugeString = new Array(100000).join('x');
clickElement.addEventListener("click", function(){
// hugeString is kept in the scope of callback forever
document.write(hugeString);
});
</script>
</body>
</html>
输出:
活动的事件
侦听器可以防止变量被垃圾收集。
使用 removeEventListener()
或将第三个参数作为 {once: true}
传递。
这样,执行一次。listener
方法将被自动删除。
Forgotten Callbacks or Timer
引起的内存泄漏及其预防技术
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<script>
for (var i = 0; i < 100000; i++) {
var obj = {
call_again: function() {
var message = this;
var value = setTimeout(function() {
message.callAgain();
}, 100000);
}
}
obj.call_again();
obj = null;
}
</script>
</body>>
</html>
输出:
timer callback
和它的绑定对象 obj
直到超时结束才被释放。
timer
可以自行重置并永远执行。因此,内存空间将始终保留,永远不会空闲。
在 JavaScript 中如何避免被遗忘的回调或计时器
通过在 setTimeout()
或 setInterval()
中提供参考,并在不再需要它们时直接调用删除该函数。
相关文章
Do you understand JavaScript closures?
发布时间:2025/02/21 浏览次数:108 分类:JavaScript
-
The function of a closure can be inferred from its name, suggesting that it is related to the concept of scope. A closure itself is a core concept in JavaScript, and being a core concept, it is naturally also a difficult one.
Do you know about the hidden traps in variables in JavaScript?
发布时间:2025/02/21 浏览次数:178 分类:JavaScript
-
Whether you're just starting to learn JavaScript or have been using it for a long time, I believe you'll encounter some traps related to JavaScript variable scope. The goal is to identify these traps before you fall into them, in order to av
How much do you know about the Prototype Chain?
发布时间:2025/02/21 浏览次数:150 分类:JavaScript
-
The prototype chain can be considered one of the core features of JavaScript, and certainly one of its more challenging aspects. If you've learned other object-oriented programming languages, you may find it somewhat confusing when you start
用 jQuery 检查复选框是否被选中
发布时间:2024/03/24 浏览次数:102 分类:JavaScript
-
在本教程中学习 jQuery 检查复选框是否被选中的所有很酷的方法。我们展示了使用直接 DOM 操作、提取 JavaScript 属性的 jQuery 方法以及使用 jQuery 选择器的不同方法。你还将找到许多有用的
jQuery 中的 Window.onload 与 $(document).ready
发布时间:2024/03/24 浏览次数:180 分类:JavaScript
-
本教程演示了如何在 jQuery 中使用 Window.onload 和 $(document).ready 事件。