你需要知道的JavaScript内存空间知识

我穿越了,文章写于2019-11-24。

前言

" 相信接触过Java、Python等后端语言的同学来说,内存空间是一个老生常谈的话题,但是作为前端开发的同学来说,这个并不会被经常提及,并且在日常编码中并不会注意一些细节问题。比如面试中常会问到的深拷贝与浅拷贝、按值传递和按引用传递等,如果从内存空间的角度去理解,会发现对你JS又有了更深的理解。 "

01 内存生命周期

在JS中,一般可以将内存分为两种:栈(包含池)、堆。其声明周期可以大概分为三个阶段:

  • 内存分配(声明)
  • 内存读写(使用)
  • 内存回收(销毁)

02 栈内存与基础数据类型

JS基础数据类型:Number、String、Boolean、Null、undefined、symbol、bigInt(自行了解)。

以上这些值都有固定大小,一般都保存在栈内存中,由系统分配固定的内存空间大小。我们在操作的时候直接操作内存中的值,即也就是在传递中是按值传递,遵循后进先出的原则进行读取。

需要强调的是,JS在执行过程中执行流进入一个函数时,会生成一个当前函数的执行环境(EC),并且推入到栈内存中,即我们所说的环境栈。所以JS在执行过程中消耗的是栈内存。

03 堆内存与引用数据类型

JS引用数据类型:Object、Array、Date、RegExp等。

引用数据类型的值时保存在堆内存中的对象,其内存空间大小是动态分配的。需要注意的是,JavaScript中不能直接访问堆内存中的位置,即不能直接操作对内存对象。而我们在平时操作引用数据类型的时候,其实操作的是这个对象的内存地址。相对应的,这个地址会被保存在栈内存中,形成一个映射关系。

举个例子:

js 复制代码
var a = { b: 1 }; 
var c = 100; 
function fn(a1, c1) { 
    a1.b = 1000; 
    a1 = null; 
    c1 = 200; 
} 
fn(a, c); 
console.log(a); 
console.log(c);

这是一道简单的题目,但是很好的表达了上面的堆栈原理。

答案是:{b: 1000}和100

当传递a的时候,实际上传递的是当前a对象的引用(地址)给了a1,其存储在栈内存中,执行a1.b = 1000进行修改的时,会通过这个地址去操作堆内存的对象,将b的值改为1000;接着a1 赋值为null,那么这时候a1就不会再指向堆内存,但是a的引用还是存在,所以对象变为修改后的{b: 1000},这就是所谓的按引用传递

而当传递实参c给形参c1的过程中,会把100直接复制新的一份给了c1,此时修改c1200后,实际上操作的就是c1这个变量,而不会影响原来的c,即该过程是按值传递。

04 内存回收

JavaScript中,自带有垃圾回收机制。其工作原理是会在每个固定时间执行一次内存释放操作,它内部有一套具体的回收机制,通过这个机制去找那些不再使用的值,回收对应内存。

标记清除法

这个是目前JavaScript最常用的垃圾收集方式。

请看下面代码

js 复制代码
var a = 100;
console.log(a + 10086);
a = null;

可以理解为当JS执行流进入这个环境的时候,会首先将a标记为"进入环境",当a离开环境时(a = null),则将其标记为"离开环境"。在垃圾收集器运行时,回收标记为"离开环境"的变量,释放内存。

引用计数法

这个是早期Netscape浏览器下一种不太常见的垃圾收集策略,由于这种方式不能回收循环引用的变量,导致对应内存不能被及时回收。后面放弃了这种方式,转而采用了标记清除来实现。

引用计数算法定义"内存不再使用"的标准很简单,就是看一个变量的引用次数是否为0。如果为0,说明该变量已经不再需要了。

综合以上,我们在日常开发中需要注意当变量不需要再使用的时候,请将其内存及时归还(赋值为null),特别是全局变量、定时器、DOM节点、闭包等等。

相关推荐
前端开发爱好者3 分钟前
Vue 3.6 将正式进入「无虚拟 DOM」时代!
前端·javascript·vue.js
天天摸鱼的java工程师7 分钟前
MySQL 动态查询条件导致索引失效如何优化?
java·后端·面试
天天摸鱼的java工程师8 分钟前
MySQL 深分页如何进行性能优化?
java·后端·面试
Mike_jia10 分钟前
Snapdrop:开源跨平台文件传输的革命者——从极简部署到企业级实战全解析
前端
晴殇i11 分钟前
一行代码生成绝对唯一 ID:告别 Date.now() 的不可靠方案
前端·javascript·面试
徐小夕14 分钟前
pxcharts-pro, 支持百万数据渲染的多维表格编辑器
前端·javascript·vue.js
独立开阀者_FwtCoder17 分钟前
Vue 3.6 将正式进入「无虚拟 DOM」时代!
前端·javascript·后端
SHERlocked9319 分钟前
C++ 中的编译和链接
c++·面试·编译原理
山河木马22 分钟前
前端学C++可太简单了:-> 操作符
前端·javascript·c++
独立开阀者_FwtCoder29 分钟前
前端开发的你,其实并没有真的掌握img标签!
前端·vue.js·github