JavaScript 数据存储机制
一、栈与堆的概念
在 JavaScript 中,数据的存储主要依靠两种内存区域:栈(Stack) 和 堆(Heap)。
- 栈:一种先进后出的数据结构,存储空间较小,访问速度快
- 堆:一种树形结构,存储空间较大,访问速度相对较慢
理解这两种内存区域的区别,对于理解 JavaScript 的数据存储机制至关重要。
二、简单数据类型的存储
1. 什么是简单数据类型
JavaScript 的简单数据类型(也称基本数据类型)包括:
number:数字类型string:字符串类型boolean:布尔类型undefined:未定义类型null:空类型
2. 存储方式
简单数据类型直接将其值存储在栈内存中。
例如:
javascript
let a = 10;
let b = "hello";
let c = true;
它们在内存中的存储如下:
| 变量名 | 内存地址 | 栈中的值 |
|---|---|---|
| a | 0x001 | 10 |
| b | 0x002 | "hello" |
| c | 0x003 | true |
3. 值传递的特性
简单数据类型在进行赋值操作时,是将值直接复制一份给新的变量,修改新变量不会影响原变量。
javascript
let num1 = 10;
let num2 = num1; // 将 num1 的值复制一份给 num2
num2 = 20; // 修改 num2,不影响 num1
console.log(num1); // 输出:10
console.log(num2); // 输出:20
原理图:
赋值前: 赋值后:
num1 → 10 num1 → 10
num2 → ? num2 → 10(复制了一份)
三、复杂数据类型的存储
1. 什么是复杂数据类型
JavaScript 的复杂数据类型(也称引用数据类型)包括:
object:对象array:数组function:函数
2. 存储方式
复杂数据类型在栈中存储的是地址(指针),而实际的数据内容存储在堆内存中。
例如:
javascript
let obj = { name: "张三", age: 18 };
let arr = [1, 2, 3, 4, 5];
它们在内存中的存储如下:
| 变量名 | 栈中的值(地址) | 堆中的实际数据 |
|---|---|---|
| obj | 0x101 | { name: "张三", age: 18 } |
| arr | 0x202 | 1, 2, 3, 4, 5 |
3. 引用传递的特性
复杂数据类型在进行赋值操作时,是将栈中的地址复制一份给新的变量,两个变量指向同一个堆中的数据。
javascript
let obj1 = { name: "张三" };
let obj2 = obj1; // 将 obj1 的地址复制一份给 obj2
obj2.name = "李四"; // 通过 obj2 修改数据
console.log(obj1.name); // 输出:李四
console.log(obj2.name); // 输出:李四
原理图:
赋值后:
obj1 → 0x101 ──┐
├──→ { name: "李四" }(堆中)
obj2 → 0x101 ──┘
四、const 与数据类型的关系
1. const 的作用
const 声明的变量,使其引用不可改变,即变量指向的地址不能改变。
2. 简单数据类型使用 const
对于简单数据类型,由于值直接存储在栈中,且 const 保证引用不变,所以不可以修改。
javascript
const num = 10;
num = 20; // 报错:Assignment to constant variable.
原因:简单数据类型的值就存储在栈中,const 保证了栈中的值不可改变。
3. 复杂数据类型使用 const
对于复杂数据类型,const 保证的是栈中的地址不变,但堆中的数据可以修改。
javascript
const obj = { name: "张三" };
obj.name = "李四"; // 可以执行,不报错
console.log(obj.name); // 输出:李四
javascript
const obj = { name: "张三" };
obj = { name: "李四" }; // 报错:Assignment to constant variable.
原因:const 保证的是栈中存储的地址 0x101 不变,但堆中的 { name: "张三" } 可以被修改为 { name: "李四" }。
4. 对比总结
| 数据类型 | const 修饰后 | 可以修改 | 说明 |
|---|---|---|---|
| 简单数据类型 | const num = 10 | ❌ | 值直接存在栈中,地址即值,不可改 |
| 复杂数据类型 | const obj = {...} | ✅ | 栈中存地址,地址不可改,但堆中数据可改 |