网易首页 > 网易号 > 正文 申请入驻

javascript中的内存管理

0
分享至

简介

在c语言中,我们需要手动分配和释放对象的内存,但是在java中,所有的内存管理都交给了java虚拟机,程序员不需要在手动进程内存的分配和释放,大大的减少了程序编写的难度。

同样的,在javascript中,内存管理也是自动进行的,虽然有自动的内存管理措施,但是这并不意味着程序员就不需要关心内存管理了。

本文将会进行详细的介绍javascript中的内存管理策略。

内存生命周期

对于任何程序来说,内存的生命周期通常都是一样的。

可以分为三步:

  1. 在可用空间分配内存

  2. 使用该内存空间

  3. 在使用完毕之后,释放该内存空间

所有的程序都需要手动执行第二步,对于javascript来说,第1,3两步是隐式实现的。

我们看下javascript中分配内存空间的例子。

通过初始化分配内存空间:

var n = 123; // 为数字分配内存
var s = 'azerty'; // 为String分配内存

var o = {
a: 1,
b: null
}; // 为对象分配内存

// 为数组分配内存
var a = [1, null, 'abra'];

function f(a) {
return a + 2;
} // 为函数分配内存

通过函数调用分配内存空间:

var d = new Date(); // 通过new分配date对象

var e = document.createElement('div'); // 分配一个DOM对象

var s = 'azerty';
var s2 = s.substr(0, 3); // 因为js中字符串是不可变的,所以substr的操作将会创建新的字符串

var a = ['ouais ouais', 'nan nan'];
var a2 = ['generation', 'nan nan'];
var a3 = a.concat(a2);
// 同样的,concat操作也会创建新的字符串

释放空间最难的部分就是需要判断空间什么时候不再被使用。在javascript中这个操作是由GC垃圾回收器来执行的。

垃圾回收器的作用就是在对象不再被使用的时候进行回收。

JS中的垃圾回收器

判断一个对象是否可以被回收的一个非常重要的标准就是引用。

如果一个对象被另外一个对象所引用,那么这个对象肯定是不能够被回收的。

引用计数垃圾回收算法

引用计数垃圾回收算法是一种比较简单和简洁的垃圾回收算法。他把对象是否能够被回收转换成了对象是否仍然被其他对象所引用。

如果对象没有被引用,那么这个对象就是可以被垃圾回收的。

我们举一个引用计数的例子:

var x = {
a: {
b: 2
}
};
//我们创建了两个对象,a对象和a外面用大括号创建的对象。
// 我们将大括号创建的对象引用赋值给了x变量,所以x拥有大括号创建对象的引用,该对象不能够被回收。
// 同时,因为a对象是创建在大括号对象内部的,所以大括号对象默认拥有a对象的引用
// 因为两个对象都有引用,所以都不能够被垃圾回收

var y = x; //我们将x赋值给y,大括号对象现在拥有两个引用

x = 1; // 我们将1赋值给x,这样只有y引用了大括号的对象

var z = y.a; // 将y中的a对象引用赋值给z,a对象拥有两个引用

y = 'flydean'; // 重新赋值给y,大括号对象的引用数为0,大括号对象可以被回收了,但是因为其内部的a对象还有一个z在被引用
// 所以暂时不能被回收

z = null; // z引用也被重新赋值,a对象的引用数为0,两个对象都可以被回收了

引用计数的一个缺点就是可能会出现循环引用的情况。

考虑下面的一个例子:

function f() {
var x = {};
var y = {};
x.a = y; // x references y
y.a = x; // y references x

return 'flydean';
}

f();

在上面的例子中,x中的a属性引用了y。而y中的a属性又引用了x。

从而导致循环引用的情况,最终导致内存泄露。

在实际的应用中,IE6 和IE7 对DOM对象使用的就是引用计数的垃圾回收算法,所以可能会出现内存泄露的情况。

var div;
window.onload = function() {
div = document.getElementById('myDivElement');
div.circularReference = div;
div.lotsOfData = new Array(10000).join('*');
};

上面的例子中,DOM中的myDivElement元素使用circularReference引用了他本身,如果在引用计数的情况下,myDivElement是不会被回收的。

当myDivElement中包含了大量的数据的时候,即使myDivElement从DOM tree中删除了,myDivElement也不会被垃圾回收,从而导致内存泄露。

Mark-and-sweep回收算法

讲到这里,大家是不是觉得JS的垃圾回收算法和java中的很类似,java中也有引用计数和mark-and-sweep清除算法。

这种回收算法的判断标准是对象不可达。

在javascript中,通过扫描root对象(JS中的root对象那些全局对象),然后找到这些root对象的引用对象,然后再找到这些被引用对象的引用对象,一层一层的往后查找。

最后垃圾回收器会找到所有的可达的对象和不可达的对象。

使用不可达来标记不再被使用的对象可以有效的解决引用计数法中出现的循环引用的问题。

事实上,现在基本上所有的现代浏览器都支持Mark-and-sweep回收算法。

调试内存问题

如果发送了内存泄露,我们该怎么调试和发现这个问题呢?

在nodejs中我们可以添加–inspect,然后借助Chrome Debugger来完成这个工作:

node --expose-gc --inspect index.js

上面的代码将会开启nodejs的调试功能。

我们看下输出结果:

Debugger listening on ws://127.0.0.1:9229/88c23ae3-9081-41cd-98b0-d0f7ebceab5a
For help, see: https://nodejs.org/en/docs/inspector

结果告诉了我们两件事情,第一件事情就是debugger监听的端口。默认情况下将会开启127.0.0.1的9229端口。并且分配了一个唯一的UUID以供区分。

第二件事情就是告诉我们nodejs使用的调试器是Inspector。

使用Chrome devTools进行调试的前提是我们已经开启了 –inspect模式。

在chrome中输入chrome://inspect:

我们可看到chrome inspect的界面,如果你本地已经有开启inspect的nodejs程序的话,在Remote Target中就可以直接看到。

选中你要调试的target,点击inspect,即可开启Chrome devTools调试工具:

你可以对程序进行profile,也可以进行调试。

闭包Closures中的内存泄露

所谓闭包就是指函数中的函数,内部函数可以访问外部函数的参数或者变量,从而导致外部函数内部变量的引用。

我们看一个简单闭包的例子:

function parentFunction(paramA)
var a = paramA;
function childFunction()
return a + 2;
return childFunction();

上面的例子中,childFunction引用了parentFunction的变量a。只要childFunction还在被使用,a就无法被释放,从而导致parentFunction无法被垃圾回收。事实上Closure默认就包含了对父function的引用。

我们看下面的例子:


特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
王楚钦为何逆转松岛夺冠!赛后说出大实话,邓亚萍点评一针见血

王楚钦为何逆转松岛夺冠!赛后说出大实话,邓亚萍点评一针见血

小徐讲八卦
2026-04-06 05:07:16
美论坛:为什么中国在明确我们不会偿还的情况下还要购买美债?

美论坛:为什么中国在明确我们不会偿还的情况下还要购买美债?

闻识
2026-04-05 23:12:22
美媒:中国应对中东危机展现惊人韧性

美媒:中国应对中东危机展现惊人韧性

参考消息
2026-04-06 16:28:04
阿根廷国脚、热刺队长合同泄密!亲爹爆料解约金:7000万美元!

阿根廷国脚、热刺队长合同泄密!亲爹爆料解约金:7000万美元!

仰卧撑FTUer
2026-04-06 20:19:04
恩爱剧本不演了?奚梦瑶提离婚,何猷君掀桌子私生子传闻真相大白

恩爱剧本不演了?奚梦瑶提离婚,何猷君掀桌子私生子传闻真相大白

秋姐居
2026-04-04 22:23:29
6岁女童走失后续:有新发现 奶茶店主做出回应,可疑人浮出水面!

6岁女童走失后续:有新发现 奶茶店主做出回应,可疑人浮出水面!

普陀动物世界
2026-04-06 18:42:33
火箭取得本季最长连胜!火记:6连胜是最佳表现 关键时刻终于赢球

火箭取得本季最长连胜!火记:6连胜是最佳表现 关键时刻终于赢球

Emily说个球
2026-04-06 14:10:41
大家一定要做好心理准备,周边的局势已经越来越紧张了

大家一定要做好心理准备,周边的局势已经越来越紧张了

安安说
2026-04-05 11:23:47
南京博物院事件真相来了:果然,那些人真狗啊!

南京博物院事件真相来了:果然,那些人真狗啊!

李月亮
2026-02-10 20:58:01
不装阔不套近乎!李亚鹏喊话张雪:钱现在掏不出,但兄弟我拉群

不装阔不套近乎!李亚鹏喊话张雪:钱现在掏不出,但兄弟我拉群

阿讯说天下
2026-04-06 10:56:01
美军跳伞飞行员身背“小金库”,步枪金条电台一应俱全,非常难捉

美军跳伞飞行员身背“小金库”,步枪金条电台一应俱全,非常难捉

利刃号
2026-04-05 23:38:07
潜伏在中国的反华家族,靠大陆收入上亿,今国家出手下场大快人心

潜伏在中国的反华家族,靠大陆收入上亿,今国家出手下场大快人心

混沌录
2026-04-05 16:33:20
1969年,教员为什么对贺帅不满?二人之间到底有何分歧?

1969年,教员为什么对贺帅不满?二人之间到底有何分歧?

阿胡
2025-02-23 13:09:21
新中国成立后,清政府遗留7.3亿两白银烂账,主席一招便成功化解

新中国成立后,清政府遗留7.3亿两白银烂账,主席一招便成功化解

唠叨说历史
2026-01-07 14:51:34
年度最佳,这部9分科幻美剧值得一看

年度最佳,这部9分科幻美剧值得一看

来看美剧
2026-04-06 19:56:20
突发!8.4万散户假期踩雷:两家财务造假公司下周被ST,两家直接退市

突发!8.4万散户假期踩雷:两家财务造假公司下周被ST,两家直接退市

股市皆大事
2026-04-06 10:47:12
2026年985大学排名变了:浙大并列第3,南大第7,哈工大跌至第10

2026年985大学排名变了:浙大并列第3,南大第7,哈工大跌至第10

Delete丨CC
2026-04-06 12:49:50
奇兵5记三分,山东男篮大胜广东,高诗岩15+6点名徐杰 争三占先机

奇兵5记三分,山东男篮大胜广东,高诗岩15+6点名徐杰 争三占先机

替补席看球
2026-04-06 21:35:55
法媒:海湾国家军事实力几何?

法媒:海湾国家军事实力几何?

参考消息
2026-04-05 20:04:08
国务院831号令:6月1日起统一执行!家家户户用水将迎7大变化

国务院831号令:6月1日起统一执行!家家户户用水将迎7大变化

小影的娱乐
2026-04-06 18:34:51
2026-04-06 22:12:49
flydean程序那些事
flydean程序那些事
最通俗的解读,最深刻的干货!
356文章数 438关注度
往期回顾 全部

科技要闻

折叠屏iPhone要来了,富士康已在试产!

头条要闻

特朗普咆哮式发帖威胁伊朗 美政界人士:他像精神错乱

头条要闻

特朗普咆哮式发帖威胁伊朗 美政界人士:他像精神错乱

体育要闻

球员系列赛大满贯!赵心童10-3世界第一 加冕赛季第4冠

娱乐要闻

唐嫣罗晋新加坡遛娃,6岁女儿身高抢镜

财经要闻

史诗级暴跌"一周年" A股接下来如何走?

汽车要闻

阿维塔06T快上市了 旅行车还能这么玩?

态度原创

游戏
旅游
亲子
本地
公开课

PS5预购榜单《星空》稳坐欧美第一 港服偏爱小萝莉

旅游要闻

别人放假,四川“带娃”:春假清明接力,这波“天降流量”接住了吗?

亲子要闻

中泰小萌娃的快乐日常,简单又治愈~

本地新闻

跟着歌声游安徽,听古村回响

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版