总述

  • C这种底层语言,一般有内存管理的接口,malloc(),free()
  • 现代高级语言一般不直接管理内存
  • 程序使用的两种不同类型的内存: 局部变量,全局变量

内存管理

栈内存-stack

  • CPU管理栈空间
  • 栈主要用于保存执行当前函数的本地上下文数据
  • 栈的大小受操作系统的限制

堆内存-heap

  • 应用程序管理堆内存
  • 一般用来保存全局变量和状态或者栈中指针引指向的时机数据
  • 堆内存可以动态的增加,只要服务器上有空闲的内存
  • 大的局部变量也可能保存在堆空间,只在栈中保存指针

内存泄漏

JavaScript高级程序设计(第四版)

4.4 小结

JavaScript变量可以保存两种类型的值:原始值和引用值。原始值可能是以下6种原始数据类型之一:Undefined、Null、Boolean、Number、String和Symbol。原始值和引用值有以下特点。
- 原始值大小固定,因此保存在栈内存上。
- 引用值是对象,存储在堆内存上。
任何变量(不管包含的是原始值还是引用值)都存在于某个执行上下文中(也称为作用域)。这个上下文(作用域)决定了变量的生命周期,以及它们可以访问代码的哪些部分。执行上下文可以总结如下。
- 变量的执行上下文用于确定什么时候释放内存。
JavaScript是使用垃圾回收的编程语言,开发者不需要操心内存分配和回收。

10.13 尾调用优化

尾调用优化的条件就是确定外部栈帧真的没有必要存在了。涉及的条件如下:
- 代码在严格模式下执行;
- 外部函数的返回值是对尾调用函数的调用;
- 尾调用函数返回后不需要执行额外的逻辑;
- 尾调用函数不是引用外部函数作用域中自由变量的闭包。
这个优化在递归场景下的效果是最明显的,因为递归代码最容易在栈内存中迅速产生大量栈帧。

11.1 异步编程

JavaScript引擎会在创建期约时尽可能保留完整的调用栈。在抛出错误时,调用栈可以由运行时的错误处理逻辑获取,因而就会出现在栈追踪信息中。当然,这意味着栈追踪信息会占用内存,从而带来一些计算和存储成本。

Dart