一篇带你了解js中变量的存储位置

121 阅读4分钟

JS中变量的存储位置

在javascript中,变量的存储位置由其的数据类型决定(基本数据类型和引用数据类型),然后主要分为栈内存(stack)和堆内存(heap)这两个部分。

一.基本数据类型

一般基础数据类型存于栈内存中:包括number,string,boolean,null,symbols,bigint。

变量的方式:这种变量值是直接存储在栈内存之中,访问时可以直接读取这个数值,速度极快

下面给出一些示例代码:

let num = 10; // 栈中直接存 num = 10

let str = "hello"; // 栈中直接存 str = "hello"

它的优点也是显而易见:数据大小是为固定,按值传递(而且在赋值变量的时候会创建独立副本);

二.引用数据类型

引用数据类型存储的结构相比较基本数据类型来说复杂一点,采用的是"栈内存存地址+堆内存存数据"的方式

栈内存存地址:只存数据所在的位置信息,而不存实际内容

举个例子就类似快递站给包裹贴的"取件码",只存它的具体位置,而不存它的具体内容

特点是:空间小,读取快,随去随用

堆内存存数据:存引用数据的具体内容,比如对象的属性,数组的元素等

举个例子就类似快递里的包裹,里面装的实际东西

特点是:空间大,可存复杂数据,但查找时需要先查栈内存的地址,再查堆内存的数据,速度比单一栈内存慢

示例代码

// 数组存储
let arr = [1, 2, 3];  
console.log(arr[0]); // 输出:1  

// 存储逻辑:  
// 栈中存arr变量,指向堆中[1,2,3]的地址  
// 堆中存储数组元素

// 函数存储与调用  
function add(a, b) {  
  return a + b;  
}  
let result = add(5, 10);  
console.log(result); // 输出:15  

// 存储逻辑:  
// 栈中存add变量,指向堆中函数定义(代码逻辑)的地址  
// 调用时栈帧存储参数a=5、b=10

三、函数调用时的存储(栈帧)

当函数在执行时,会在栈中创建栈帧

何为栈帧:栈帧是函数执行时在栈内存中创建的临时存储空间,也叫执行上下文栈帧。它像一个容器,保存函数运行时需要的所有信息,函数执行完毕后立即销毁,遵循“后进先出”的栈结构规则。

函数的局部变量(基本类型值直接存,引用类型存地址)。

示例代码

function demo() {
  let num = 10;        // 栈帧中存num=10(基本类型)
  let arr = [1, 2, 3]; // 栈帧中存arr的堆地址,堆中存[1,2,3]
}

函数的参数、执行环境等信息。

function sum(a, b) {
  // 栈帧中存ab的参数值(如sum(5, 6)时,a=5b=6)
  return a + b;
}

函数执行完毕后,栈帧被销毁然后释放内存。

四.栈内存和堆内存的核心区别对比

在了解完大致的栈内存和堆内存的信息之后,我们可以总结出来它们的区别

  1. 存储内容

• 栈内存:存储变量的具体值。

• 堆内存:栈中存储数据的内存地址,堆中存储数据的具体内容。

  1. 分配方式

• 栈内存:由系统自动分配和释放,随函数调用的执行上下文入栈或出栈。

• 堆内存:动态分配空间,依赖 JavaScript 的垃圾回收机制释放不再被引用的数据。

  1. 访问速度

• 栈内存:直接读取值,访问速度极快。

• 堆内存:需通过地址间接访问数据,速度较慢。

  1. 数据传递方式

• 栈内存(基本类型):按值复制,新变量与原变量相互独立。

• 堆内存(引用类型):按引用复制,多个变量共享同一堆数据,修改会相互影响。

总结:基本类型在栈中的“快”与“轻”

栈内存的特点决定了基本类型的操作速度极快(直接存取),且内存管理简单(系统自动处理),但也因为空间固定,所以无法存储复杂结构(比如对象的多个属性),这也是引用类型需要堆内存的原因。

最后

大家都看到这了,不妨点一个小赞,路过大佬们觉得有什么问题可以打在评论区,我看到了也会在内容上多做改动,谢谢大家