JavaScript的内存管理

  • JavaScript会在定义数据时为我们分配内存。
  • 但是内存分配方式是一样的吗?
    • JS对于原始数据类型内存的分配会在执行时, 直接在栈空间进行分配;
    • JS对于复杂数据类型内存的分配会在堆内存中 开辟一块空间,并且将这块空间的指针返回值 变量引用;

常见的GC算法 – 引用计数 (不重要)

  • 引用计数:
    • 一个对象有一个引用指向它时,那么这个对象的引用就+1;
    • 当一个对象的引用为0时,这个对象就可以被销毁掉
  • 这个算法有一个很大的弊端就是会产生循环引用; image.png

常见的GC算法 – 标记清除 (不重要)

  • 标记清除:
    • 标记清除的核心思路是可达性
    • 这个算法是设置一个根对象(root object),垃圾回收器会定期从这个根开始,找所有从根开始有引用到的对象,对于哪些 没有引用到的对象,就认为是不可用的对象;
    • 这个算法可以很好的解决循环引用的问题; image.png

闭包的定义

  • 一个普通的函数function,如果它可以访问外层作用域的自由变量,那么这个函数和周围环境就是一个闭包;
    • 从广义的角度来说:JavaScript中的函数都是闭包;
    • 从狭义的角度来说:JavaScript中一个函数,如果访问了外层作用域的变量,那么它是一个闭包;

闭包的访问过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function createAdder(count) {
function adder(num) {
return count + num
}

return adder
}

var adder5 = createAdder(5)
adder5(100)
adder5(55)
adder5(12)

var adder8 = createAdder(8)
adder8(22)
adder8(35)
adder8(7)

console.log(adder5(24))
console.log(adder8(30))

// 永远不会再使用adder8
// 内存泄漏: 对于那些我们永远不会再使用的对象, 但是对于GC来说, 它不知道要进行释放的对应内存会依然保留着
adder8 = null

1.第一次调用createAddr
image.png
2.调用createAddr完成
image.png
3.内部addr执行完成
image.png
4.第二次执行createAddr
image.png