JavaScript内存空间

 

栈(stack)

JavaScript中Array数组模拟栈:

var arr = [1, 2, 3, 4, 5];

arr.push(6); // 存入数据 arr -> [1, 2, 3, 4, 5, 6]
arr.pop();   // 取出数据 arr -> [1, 2, 3, 4, 5]

堆(heap)

    堆的特点是"无序"key-value"键值对"存储方式。

   "堆的存取方式跟顺序没有关系,不局限出入口"

 

队列 (queue)

 JavaScript中Array数组模拟队列: 

var arr = [1, 2, 3, 4, 5];
// 队尾in
arr.push(6);    // 存入 arr -> [1, 2, 3, 4, 5, 6]
// 队头out
arr.shift();    // 取出 arr -> [2, 3, 4, 5, 6]

栈、堆、队列在JavaScript中的应用

1. 代码运行方式(栈应用/函数调用栈)

   JavaScript中函数的执行过程,其实就是一个入栈出栈的过程:

  1. 当脚本要调用一个函数时,JS解析器把该函数推入栈中(push)并执行
  2. 当函数运行结束后,JS解析器将它从堆栈中推出(pop)

     

2. 内存存储(栈、堆)

       JS中的基础数据类型,这些值都有固定的大小,往往都保存在栈内存中,因此基础数据类型都是按值访问

       JS的引用数据类型,比如数组Array,它们值的大小是不固定的。引用数据类型的值是保存在堆内存中的对象。JS不允许直接访问堆内存中的位置,因此我们不能直接操作对象的堆内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。因此,引用类型的值都是按引用访问的。这里的引用,我们可以粗浅地理解为保存在栈内存中的一个地址,该地址与堆内存的实际值相关联。

3. 事件轮询(队列)

  JavaScript中事件轮询(Event Loop)的执行机制,就是采用队列的存取方式,因事件轮询(Event Loop)也是JS基础中的一个比较难理解的知识点。

深浅拷贝

  将一个变量的值赋值给另一个变量,相当于在栈内存中创建了一个新的内存空间,然后从栈中复制值,存储到这个新空间中。对于基本类型,栈中存储的就是它自身的值,所以新内存空间存储的也是一个值。直接改变新变量的值,不会影响到旧变量的值,因为他们值存储的内存空间不同。

复制代码
// 基本类型复制变量
var a = 10;
var b = a;
b = 20;

a // 10
b // 20
复制代码

 而对于引用类型来说,同样是复制栈中存储的值。但是栈存储的只是其引用地址,其具体的值存储在堆中。变量复制仅复制栈中存储的值,不会复制堆中存储的值,所以新变量在栈中的值是一个地址指针。

复制代码
// 引用类型复制变量
var a = { age: 27 };
var b = a;
b.age = 29;

a.age == b.age; // 29
复制代码

 

    可见,变量复制赋值,都属于栈存储拷贝,因此深浅拷贝可以这样区分:

  • "浅拷贝:栈存储拷贝"
  • "深拷贝:栈堆存储拷贝"

   深拷贝会同时开辟新的栈内存,堆内存空间。

复制代码
// 利用JSON对象方法实现深拷贝
var a = { age: 27 };
var b = JSON.parse(JSON.stringify(a));
b.age = 29;

a.age // 27
b.age // 29
复制代码

 

未完,待续......
原文地址:https://www.cnblogs.com/zhishiyv/p/12105299.html