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) {
// 栈帧中存a和b的参数值(如sum(5, 6)时,a=5,b=6)
return a + b;
}
函数执行完毕后,栈帧被销毁然后释放内存。
四.栈内存和堆内存的核心区别对比
在了解完大致的栈内存和堆内存的信息之后,我们可以总结出来它们的区别
- 存储内容
• 栈内存:存储变量的具体值。
• 堆内存:栈中存储数据的内存地址,堆中存储数据的具体内容。
- 分配方式
• 栈内存:由系统自动分配和释放,随函数调用的执行上下文入栈或出栈。
• 堆内存:动态分配空间,依赖 JavaScript 的垃圾回收机制释放不再被引用的数据。
- 访问速度
• 栈内存:直接读取值,访问速度极快。
• 堆内存:需通过地址间接访问数据,速度较慢。
- 数据传递方式
• 栈内存(基本类型):按值复制,新变量与原变量相互独立。
• 堆内存(引用类型):按引用复制,多个变量共享同一堆数据,修改会相互影响。
总结:基本类型在栈中的“快”与“轻”
栈内存的特点决定了基本类型的操作速度极快(直接存取),且内存管理简单(系统自动处理),但也因为空间固定,所以无法存储复杂结构(比如对象的多个属性),这也是引用类型需要堆内存的原因。
最后
大家都看到这了,不妨点一个小赞,路过大佬们觉得有什么问题可以打在评论区,我看到了也会在内容上多做改动,谢谢大家