1、理解 栈 堆 队列
a、栈 (stack)
- 先进后出(类似吃了吐,乒乓球盒子,羽毛球盒子)
- 存放基本类型(null,undefined,Number,Boolean,Symbol,String)-在内存中有固定大小
b、堆 (heap)
- 存放引用类型(Object,Array,Function)–内存中大小不固定
- 根据key查找value(类似,从书架中取书)。
c、 队列
- 先进先出(类似吃了大号,类似排队吃饭)
d、变量存放
- 引用类型:先从
栈
中读取内存地址,然后再通过地址找到堆
中的值。这种叫按引用访问
*在计算机的数据结构中,栈比堆的运算速度快,Object是一个复杂的结构且可以扩展:数组可扩充,对象可添加属性,都可以增删改查。将他们放在堆中是为了不影响栈的效率。而是通过引用的方式查找到堆中的实际对象再进行操作。所以查找引用类型值的时候先去栈查找再去堆查找
2、内存机制
a、内存回收
- 局部变量:函数执行完毕,变量会自动回收。
- 全局变量:难判断什么时候回收。
b、垃圾回收算法
- 引用计数(现代浏览器不在使用)
- 标记清除(常用)
引用计数
- 说明这个对象没有用了。内存中不使用了。
- 缺点,这两个对象互相引用,就会产生内存泄漏。
demo1(正常引用计数)1
2
3
4
5var a = {} // 引用计数+1,{} 被a使用
var b = a //引用次数+1, {} 被b使用了
a = null //{}引用计数-1
b = null //{}引用计数-1
//此时为0 {}对象被回收了
demo2(缺点,内存泄漏)1
2
3
4
5
6
7
8
9
10function f(){
var o = {};
var o2 = {};
o.a = o2; // o 引用 o2,o2的引用次数是1
o2.a = o; // o2 引用 o,o的引用此时是1
return "azerty";
}
f();
标记清除
1、给内存中变量加上标记(类似Index)
2、从根部出发将能触及到的对象的标记清除。
3、删除变量,回收内存。
demo11
2
3
4
5
6
7
8
9
10
11
12
13
14
15email.message = document.createElement(“div”);
displayList.appendChild(email.message);
// 稍后从displayList中清除DOM元素
displayList.removeAllChildren();
```
### c、内存泄漏
* 例子
demo1-没有声明变量,直接使用, 在windows上赋值
```js
function fn() {
a = 'xxx' //没有声明=>window.a
window.b = 'yyy'//全局=>window.b
}
demo2-定时器忘记关闭
demo3-闭包
demo4-dom操作,创建之后忘记remove