JS:内存图

内存

计算机中所有程序的运行都是在内存中进行的,这里的内存一般指的是PC中的内存条,我们知道内存条里只能存取二进制数0和1,那么1G的内存条里能存多少个0或1呢?
1G = 10243B = 10243*8位≈85.8亿位(一个字节有8位),也就是说1G的内存可以存85.8亿个0或1。

内存分配

基本类型数据的存储

当我们写var a = 1时,这段代码被放在内存图哪里了,我们画图来进行说明。

我们以64位的电脑为例,当我们写var a = 1时,这段代码其实是两句,var aa = 1,其中a放在JS解析器里,它只是一个名字,由别人维护。而数值1分配在一个64位的内存里,并指向a。当我们写a = 2时,JS并不会另外开辟一块内存,而是将原来的数值1进行覆盖。
又比如我们写var s1 = 'abc'时,这个字符串又被分配一个64位内存用来存储,由于这个字符串共三个字节,而1个字节占16位,那么这个字符串共占48位,显然用这个分配的64位内存来存储是足够的。
又假如我们写的字符串不是三个字节,即`var s2 = ‘abcdef’,这个字符串共6个字节共96位,明显一块64位的内存不够,那么浏览器会再分配一个,知道满足为止。这些内存的存放是整齐有序的,不是杂乱无章的,这样的好处是使JS引擎更高效的读取数据。
当我们调用变量a时,a是指向那个指定的内存的,此刻数值1就被传了出去,该过程叫值传递,其它变量(基本类型)同样如此。

值传递

如果我们把变量a的值赋给变量b,即var b =a,此时浏览器会新开一个内存,用来存储数值1,也就是说如果我们给b重新赋一个不等于1的值,并不会影响到a的值。只就是‘值传递’的特点,不会影响其它变量的值。

复杂类型数据的存储

比如我们声明一个复杂类型的变量时,例如var o = {name: 'Allen'},此时这段代码又该如何存储?如果是以简单类型的存储方式,这样可行吗?
我们知道复杂类型可以添加修改属性和属性值,而内存是没有扩展性,它只能挪内存,这样显然不行。其实开发者用户那里不止一块区域,存简单类型时放在’Stack(栈)’区,该区是按顺序读写的,存复杂类型是放在’Heap(堆)’区,这片区域是无序读写的。’Stack’区就像数组一样,’Heap’区就像树型结构一样。

上面图中,‘Heap4’和’Heap100’都表示一个地址,而这个地址指向’Heap区’某一块内存区域,用来存放这些属性和属性值。如果要调用这个复杂类型的变量,首先会传个‘地址’给你,然后根据这个‘地址’到‘Heap区’去调用。该过程叫做‘址传递’。

址传递

如果我们改变o2name属性值,这会影响oname属性值,因为它们指向的都是同一个‘地址’。‘址传递’的特点是,对于复杂类型数据,改变其中一个变量的属性值,如果另一变量也指向这个‘地址’,那个这个变量的属性值也会改变。

这里只暂时讨论简单的复杂类型数据的存储,对于那些稍微复杂层层调用的函数,以后进行补充。
(未完待续)