内存空间

1、栈数据结构

处于盒子中最顶层的乒乓球5,它一定是最后被放进去,但可以最先被使用。而我们想要使用底层的乒乓球1,就必须将上面的4个乒乓球取出来,让乒乓球1处于盒子顶层。这就是栈空间先进后出,后进先出的特点

2、堆数据结构

堆数据结构是一种树状结构。它的存取数据的方式,则与书架与书非常类似。

书虽然也整齐的存放在书架上,但是只需要只知道书的名字,就可以很方便的取出想要的书,而不用像从乒乓球盒子里取乒乓球一样,非得将上面的所有乒乓球拿出来才能取到中间的某一个乒乓球。好比在JSON格式的数据中,存储的 key-value 可以是无序的,因为顺序的不同并不影响使用,只需要关心书的名字。

3、变量对象与基础数据类型

JavaScript的执行上下文生成之后,会创建一个叫做变量对象的特殊对象,JavaScript的基础数据类型往往都会保存在变量对象中。

严格意义上来说,变量对象也是存放于堆内存中,但是由于变量对象的特殊职能,我们在理解时仍然需要将其于堆内存区分开来。

基础数据类型都是一些简单的数据段,JavaScript中有5中基础数据类型,分别是Undefined、Null、Boolean、Number、String。基础数据类型都是按值访问,因为我们可以直接操作保存在变量中的实际的值。

4、队列

队列是一种先进先出(FIFO)的数据结构。正如排队过安检一样,排在队伍前面的人一定是最先过检的人。

5、引用数据类型与堆内存空间

引用数据类型(Object)是保存在堆内存空间中的对象,在Js中不允许直接访问对内存空间中的数据,因此不能直接操作对象的内存空间。在操作操作对象时,实际上是在操作对象的引用,因此引用数据类型都是按引用访问的,这里的引用我们可以理解为保存对象的一个地址,改地址与堆内存空间中的对象相关联。

var a1 = 0;   // 变量对象
var a2 = 'this is string'; // 变量对象
var a3 = ; // 变量对象
 
var b = { m: 20 }; // 变量b存在于变量对象中,{m: 20} 作为对象存在于堆内存中
var c = [1, 2, 3]; // 变量c存在于变量对象中,[1, 2, 3] 作为对象存在于堆内存中

  

// demo01.js
var a = 20;
var b = a;
b = 30;
 
// 这时a的值是多少?

  

// demo02.js
var m = { a: 10, b: 20 }
var n = m;
n.a = 15;
 
// 这时m.a的值是多少

  

在demo1中数据类型发生了一次复制行为,在demo2中数据类型发生了一次复制行为

当变量对象的数据发生复制行为时,新的变量会被分配到一个新的值,在demo1中,通过var b =a发生复制之后,虽然a与b的值都等于20,但是其实是相互独立相互不影响的值了,因此当我们修改了b的值后a的值不会发生变化。具体如图

复制前
a 20
   
复制后
a 20
b 20
b的值改变后
a 20
b 30

 

demo2中通过var n=m发生了一次复制行为。引用类型的复制同样会为新的变量自动分配一个新的值并保存在变量对象中,但不同的是,这新值,仅仅只是引用类型的一个地址指针,当地址指针相同时尽管他们相互独立,但是他们指向的对象实际上是同一个因此当n变化时,m的值也会发生变化这就是引用类型的特性。

6、内存空间管理

因为自动垃圾回收机制的存在,使我们在开发时不用关心内存机制的使用问题,内存的分配回收完全实现了自动化管理。但是认识了内存机制之后能使我们在写代码的过程当中清楚的知道自己写的代码在执行的过程当中都发生了什么,从而写出更加优秀的代码。

var a=20;

alert(a+100);

a = null;

  

上面三条语句分别对应如下的三个过程

(1)分配内存

(2)使用分配到的内存

(3)不需要时释放内存

其实前面两条都比较好理解,我们需要重点关注的是第三个过程,这里涉及Js垃圾回收机制的实现原理。

JS垃圾回收机制需要用的"引用"的概念。当一个内存空间重间中的地址能够被访问时,垃圾回收器就会认为"该数据能够被获得"。不能被获得的数据就会被打上标记,并回收内存空间。这种标记方式叫作:标记--清除算法。

这个算法会设置一个全局对象,并定期从全局对象开始查找。垃圾回收器会找到所有可以被获得与不能被获得的数据。因此在上面的列子当中,当a被设置为null时,那么刚开始分配的20变成不可访问,而很快被自动回收

注意:在局部作用域中,当函数执行完毕之后,局部作用域就没有存在的必要了,因此垃圾回收机制很容易的做出判断并回收。但在全局中,变量什么时候需要自动释放空间则很难判断,因此在开发时,应尽量使用局部变量避免使用全局变量,如果使用了全局变量则建议在不使用它时,通过a=null这样的方式手动释放引用,以确保能够及时回收内存空间

posted @ 2019-03-11 16:29  诸城布拉德皮特  阅读(193)  评论(0编辑  收藏  举报