javascript 内存的数据结构和机制原理

不了解Js 内存管理机制的web开发,不是一个好android.........

如果你想更好的学习Js高级知识,必须学会javascript 内存管理机制,这点毋庸置疑!

Js 内存特点:

  1. 内存分配:申明变量、函数、对象的时候,系统就会为他们分配内存
  2. 内存使用:读写内存时候,也就是使用变量、函数等进行操作
  3. 内存回收:使用完毕释放变量,函数,由垃圾回收机制回收不再使用的内存

JS内存分为:

栈(stack)、堆(heap)。 其中栈存放变量即基础数据类型,堆存放复杂对象即引用数据类型。

基础数据类型存放在栈内存中(undefined null boolean string number  五个基本类型),JS中的基础数据类型,有固定的大小,往往都保存在栈内存中(闭包除外),系统分配内存大小。我们可以直接操作保存在栈内存空间的值。 

引用数据类型存放在堆内存中(Array等),JS的引用数据类型,比如数组Array,它们值的大小是不固定的。引用数据类型的值是保存在堆内存中。Javascript不允许直接访问堆内存中的位置,因此我们不能直接操作。因此在操作对象时,我们都是通过操作堆内存里面的特殊的引用关系来操作对象。这里的特殊的引用,其实就是保存在栈内存中的一个地址引用,该地址引用与堆内存的实际位置相关联。因此当我们要访问堆内存中的引用数据类型时,实际上我们首先是从栈中获取了该对象的地址引用(或者地址指针),然后再从堆内存中取得我们需要的数据位置来获取数据。

栈(stack)互相不会影响,然而堆(heap)会产生一定的影响!看个来例子:

 demo1.js

var a =10;

var b = a;

b = 30;

// 这时a的值是多少?-------------10

 demo2.js

var m = { a: 20, b: 30 };

var n = m;

n.a = 15;

// 这时m.a的值是多少---------------15

看完是不是有点傻傻分不清?如说是,那就好好理解一下基本类型内存和引用类型内存在Js内存划分保存的区别,基本类型变量复制一个新变量时候会在内存里面重新划分出一块内存来存放这个新变量,所以demo1里面的a和b是两个新的内存变量!

引用类型变量复制一个新变量时候不会在内存里面重新划分出一块地方来存放这个新变量,只是在引用关系上新增,所以demo2里面的m和n是同一个的内存变量!m和n的引用都指向原来的内存,没有划分新的内存来保存新的变量。所以无论是m或者n变化,通过引用都指向原来内存,从而改变内存。

内存回收:

这里不简单的说下了,这是个大坑。。。比较难搞。。。

变量生命周期

生命周期结束的变量,当然只可能是局部变量,全局变量的生命周期直至浏览器卸载页面才会结束。局部变量只在函数的执行过程中存在。

一旦函数结束,局部变量就没有存在必要了,可以释放它们占用的内存,就像闭包,貌似函数结束了,其实还没有。垃圾回收器必须知道哪个变量有用,哪个变量没用,对于不再有用的变量打上标记,以备将来回收。用于标记无用的策略有很多,常见的有两种方式

标记清除(mark and sweep)

这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。至于怎么标记有很多种方式,比如特殊位的反转、维护一个列表等,这些并不重要,重要的是使用什么策略,原则上讲不能够释放进入环境的变量所占的内存,它们随时可能会被调用的到。

垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了,因为环境中的变量已经无法访问到这些变量了,然后垃圾回收器相会这些带有标记的变量机器所占空间。这里相当于排除法,去掉和闭包有关的,去掉环境中的,剩下的就是回收的部分!

大部分浏览器都是使用这种方式进行垃圾回收,区别在于如何标记及垃圾回收间隔而已,只有低版本IE。

引用计数(reference counting)

在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。

 

在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的

看這:

window.onload=function outerFunction(){
        var obj = document.getElementById("element");
        obj.onclick=function innerFunction(){};
    };

有没有什么感觉?没有的话看这个:

window.onload=function outerFunction(){
        var obj = document.getElementById("element");
        obj.onclick=function innerFunction(){};
       obj=null;  赋值空 便于回收
    };

IE6的垃圾回收是根据内存分配量运行的,当环境中存在256个变量、4096个对象、64k的字符串任意一种情况的时候就会触发垃圾回收器工作。

你可能感兴趣的:(javascript,内存管理,Js内存)