【JavaScript高级】内存管理与闭包:垃圾回收GC、闭包定义、访问和执行过程、内存泄漏

内存管理

所有编程语言,在代码的执行过程中都需要给它分配内存,不同的是:某些编程语言需要我们自己手动的管理内存,某些编程语言会可以自动帮助我们管理内存。

内存管理的生命周期

  1. 申请:申请你需要的内存
  2. 使用:存放一些东西,比如对象等
  3. 释放

不同的编程语言对于第一步和第三步会有不同的实现:

  • 手动管理内存:如C,C++
  • 自动管理内存:比如Java、JavaScript、Python

JavaScript 的内存管理是自动的、无形的:我们创建的原始值、对象、函数……这一切都会占用内存。但我们不需要手动对它们进行管理,JavaScript引擎会帮我们处理好它。

JavaScript会在定义数据时为我们分配内存:

  • JS对于原始数据类型内存的分配会在执行时,直接在栈空间进行分配
  • JS对于复杂数据类型内存的分配会在堆内存中开辟一块空间,变量引用其内存地址(如对象)

数据类型:

  • 基本数据类型(值类型):string、number、boolean、undefined、null、symbol
  • 复杂数据类型(引用类型):object、function、array

垃圾回收GC

内存大小有限,当内存不再需要时,我们需要对其进行释放,以腾出更多的内存空间。

手动管理内存的语言中,我们需要通过一些方式自己来释放不再需要的内存,比如free函数:

  • 这种方式非常低效,影响我们编写逻辑的代码的效率
  • 对开发者要求很高,一不小心会产生内存泄露

大部分现代编程语言都是有自己的垃圾回收机制

  • Garbage Collection,简称GC;
  • 对于那些不再使用的对象,我们称之为垃圾,需要被回收,以释放更多的内存空间
  • 而我们的语言运行环境,比如Java的JVM,JavaScript的js引擎都有内存垃圾回收器
  • 垃圾回收器我们也会简称为GC,很多地方的GC指的是垃圾回收器

GC怎么知道哪些对象是不再使用的呢?这就引出了GC的实现及对应算法。

引用计数(Reference counting)

  • 当一个对象有一个引用指向它时,那么这个对象的引用就+1
  • 当一个对象的引用为0时,这个对象就可以被销毁掉
  • 弊端:会产生循环引用

在这里插入图片描述

标记清除(mark-Sweep)

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

在这里插入图片描述

闭包

有关闭包的其他清晰讲解:学习Javascript闭包(Closure) - 阮一峰的网络日志 (ruanyifeng.com)
闭包就是能够读取其他函数内部变量的函数。

定义

在计算机科学中对闭包的定义(维基百科):

  • 是在支持 头等函数 的编程语言中,实现词法绑定的一种技术
  • 在实现上是一个结构体,它存储了一个函数和一个关联的环境(相当于一个符号查找表)

举个例子:

var name = "name"
var age = 18
var address = "address"

function foo() {
    var message = "Hello World!"
    console.log(message, name, age, address);
}

这段代码里foo函数是可以访问到name、age、address的,因为它们在一个闭包里。

MDN对JavaScript闭包的解释:

  • 一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)
  • 闭包让你可以在一个内层函数中访问到其外层函数的作用域
  • 在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来

总结:

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

闭包的访问和执行过程

看这里:JavaScript闭包的那些事~

内存泄漏

为什么会内存泄漏?

  • 在全局作用域下一些变量对一些的函数对象有引用,而函数对象的作用域中AO有引用,最终会造成这些内存都无法被释放
  • 闭包会造成内存泄露,就是上述的引用链中的所有对象都是无法释放的

如何解决:a原先是对函数对象的引用。这里我们把它赋值为null,这样函数对象就是不可达的,在GC的下一次检测中就会被销毁掉。

var a=null

浏览器的优化

V8会把AO里不用的属性释放掉。

这里只用到了count,没有用到name,所以name就被释放掉了:
在这里插入图片描述

参考

coderwhy的课
js中的内存管理
JavaScript的内存管理
JS内存管理
JavaScript闭包的那些事~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karshey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值