一、js中,变量名并不真正“存储”值,而是存储一个“引用”(指向一个内存位置)
JavaScript 的变量 = “名字(标识符)指向一个内存地址” ,
但它和 C/C++ 的变量模型非常不一样。
我帮你用你已经懂的 C 语言视角来对比解释👇
1. JS 中的变量是什么?
在 JavaScript 中:
变量名并不真正“存储”值,而是存储一个“引用”(指向一个内存位置)。 所以,const类型绑定了call stack里某块内存,无法指向其它内存
例如:
let a = 10;
JS 在内存里表现为:
a ───► [ 10 ]
如果是对象:
let obj = { x: 1 };
内存是:
obj ───► (地址0x001)
│
▼
{ x: 1 }
变量存放的是“引用 / 指针-like 地址”,不是值本身。
2. 和 C/C++ 的对比
⭕ 基本类型的比较
C:
int a = 10;
内存:
[ a: 10 ] // 变量直接存值
JS:
let a = 10;
内存:
a ───► [10]
区别:
| 语言 | 变量存储的是什么? |
|---|---|
| C/C++ | 变量本身存放值本体 |
| JS | 变量存的是“指针(引用)”,值放在别处 |
⭕ 对象(引用类型)的比较
C++:
Person p(20);
Person q = p; // 拷贝一份
q 会复制一份新的对象。
JS:
let p = { age: 20 };
let q = p; // 不会复制对象
内存:
p ──┐
▼
{ age: 20 }
▲
q ──┘
→ 两者指向同一个地址
→ 改 p / q 的内部内容会互相影响
这是 JS 和 C 最大的差异之一。
🧠 3. 那 const 为什么不能重新赋值?
因为:
const 变量名 = 某个地址;
JS 禁止你改变这个 变量名→地址 的绑定。
但允许改变“地址里的内容”。
🧠 4. 为什么说 JS 没有“真正的值类型变量”概念?
因为所有变量(包括基本类型)本质上都通过引用来实现访问。
区别只是:
-
基本类型所在的内存区域不可共享,所以拷贝时拷贝的是值
-
引用类型的地址可以共享,所以会产生“两个变量名指向同一对象”的情况
但 JS 内部机制统一:
变量只是标签 → 指向某个内存块
一句话总结:
JS 中的变量永远“指向”一个内存位置(引用语义),
与 C/C++ 的“变量就是内存” 有本质不同。
二、原始类型 VS 对象类型
原始类型(integer、null, string等)存储在call stack里,对象(对象、数组,js中数组也是一种对象类型)存储在heap里,因为对象可能很大,call stack内存较小。call stack有一块内存存储对象在heap里的地址(存储该对象的引用),从而访问对象。
//原始类型:
let age = 23; //指向某一块内存,地址为a1,该内存存23
let oldAge = age; //指向内存a1
//change age,但oldAge不应该改变,否则就失去了复制变量的意义,所以:
age = 30; //js会新增一块内存a2, 存30,age改成指向该内存地址a2.
age = 35; //改变age指向的内存a2存的值为35.
console.log(age); //35
console.log(oldAge); //23
//change oldAge:
oldAge = 40;
console.log(age); //30
console.log(oldAge); //40
//对象类型里的属性是引用类型,
//当你复制一个对象给另一个变量时,js也只是新建这个变量指向相同的的call stack内存,这个内存存储了该对象的引用。