参考

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
5
var 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
10
function 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、删除变量,回收内存。

标记清除机制
标记清除机制

demo1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
email.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