【JS背后】JavaScript中的堆栈

本文介绍JS内存中的堆栈:

  • 一、堆栈的基本概念
  • 二、堆栈与JavaScript中的基本类型和引用类型
  • 参考资料

一、堆栈的基本概念

堆(heap)和栈(stack)是两种数据结构,先进后出,只能在一端对数据进行插入和删除。

栈(stack)的寻址速度要快于堆(heap)。

内存空间中的堆栈:

结构 存放方式及大小 分配释放者 存放数据
堆(heap) 没有结构 任意存放,大小未知 程序员/由OS回收 运行时数据区对象自定义类型
栈(stack) 有结构 按次序存放,每个区块大小确定 操作系统 函数的参数值局部变量的值

数据存放的规则:

  • 栈(stack):局部的、占用空间确定的数据
    • 每个函数/方法都会建立自己的内存栈,存储函数参数和局部变量
  • 堆(heap):其他
    • 所有的对象

垃圾回收机制:

  • 随着函数/方法的执行结束,这个函数/方法的内存栈也将自然销毁
  • 堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

因此,一般来说,内存泄漏都发生在堆(heap),即某些内存空间不再被使用了,却因为种种原因,没有被系统回收。

举例说明:

1
2
3
4
5
6
7
8
public void Method1()
{
int i=4;
int y=2;
class1 cls1 = new class1();
}
  • 变量i和y:栈(stack)
    • 局部变量:只用在Method1区块之内,不会用于区块之外
    • 占用的内存空间确定:整数
  • 变量cls1:栈(stack)
    • 局部变量
    • 占用的内存空间确定:指针,指向一个对象的实例
  • 变量cls1的对象实例:堆(heap)
    • 局部变量
    • 无法确知所占用的内存空间大小

Method1方法运行结束:

  • 整个stack被清空,i、y和cls1这三个变量消失,因为它们是局部变量,区块一旦运行结束,就没必要再存在了
  • heap之中的那个对象实例继续存在,直到系统的垃圾清理机制(garbage collector)将这块内存回收

以上是堆栈的基本概念,下面重点剖析JavaScript中的堆栈。

二、堆栈与JavaScript中的基本类型和引用类型

基本类型和引用类型

JavaScript的数据类型分为两大类:

  1. 基本类型:Undefined、Null、Boolean、Number 和 String
  2. 引用类型:Object、Array、Function等,变量实际保存的是一个指针,指向另一个位置
内存分配 数据大小 访问方式 本质
基本类型 栈(stack) 确定 按值访问 数据段
引用类型 堆(heap) 不确定 按引用访问 对象
  • 复制表示对象的某个变量:操作的是对象的引用,复制指针
  • 为对象添加属性:操作的是实际的对象,修改对象

举例说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var obj1 = {name:'bangbang',age:18};
var b = obj1; // 引用类型Object
var c = obj1.age; //基本类型Number
console.log(Array.prototype.toString.call(b)); // [object Object]
console.log(Array.prototype.toString.call(c)); // [object Number]
console.log(b.name); //bangbang
console.log(c); //18
//改变b和c的值
b.name = 'yanniu';
c = 22;
console.log(obj1.name); //yanniu
console.log(obj1.age); //18
console.log(b.name); //yanniu
console.log(c); //22

b和obj1变量操作的是同一个对象,c和obj1完全独立的

  • 改变b的数据:obj1.name的数据也在改变
  • 改变c的数据:obj1.age的值没有变化

参考资料

您的支持将鼓励我继续创作!
------本文结束感谢阅读------