原始类型直接操作栈中实际值,引用类型操作指向堆中对象的地址;前者赋值复制值,后者复制地址;前者不可变,后者可变;函数参数均按值传递,但引用类型的“值”是地址。

本质区别在于值的存储位置和操作对象不同:原始类型直接操作栈中的实际值,引用类型操作的是指向堆中对象的地址。
内存位置与存储方式
原始类型(string、number、boolean、null、undefined、symbol、bigint)体积小、结构固定,值直接存在栈内存里,变量名就等于那个值。
引用类型(object、array、function、date 等)数据存在堆内存,变量在栈中只存一个地址(指针),真正内容在堆里。
赋值行为:复制值 vs 复制地址
原始类型赋值时,是把栈里的值完整拷贝一份,两个变量互不干扰:
// a 和 b 各自独立
let a = 42;
let b = a;
b = 99;
console.log(a); // 42
引用类型赋值时,拷贝的是地址,多个变量可能指向同一块堆内存:
// obj1 和 obj2 共享同一个对象
let obj1 = {x: 1};
let obj2 = obj1;
obj2.x = 99;
console.log(obj1.x); // 99
可变性与属性操作
原始类型不可变(immutable):任何“修改”都是创建新值并重新赋值,原值不受影响。
比如字符串调用 toUpperCase() 返回新字符串,原变量内容不变。
引用类型可变(mutable):通过任一引用修改属性或元素,其他引用立刻可见变化。
但重新赋值(如 obj2 = {})只是让变量指向新地址,不影响原来对象。
函数参数传递统一按值,但“值”的含义不同
JS 所有函数参数都是按值传递——这点没有例外。
对原始类型,“值”就是数据本身;
对引用类型,“值”是内存地址。
所以函数内改 param.prop 会影响外部对象,但 param = {} 不会。











