引用赋值指变量存储并复制指向堆内存的地址,而非数据本身;因此赋值后两变量共享同一对象,修改属性/元素会相互影响,但重新赋值仅改变自身引用,不影响对方。

JavaScript 中的引用数据类型(如对象、数组、函数、Map、Set 等)在赋值时,变量存储的是指向堆内存中实际数据的引用(地址),而不是数据本身。所以赋值操作本质上是“复制引用”,而非复制值——这常被通俗称为“引用传递”,但严格来说,JS 中所有参数和赋值都是值传递,只是这个“值”恰好是一个内存地址。
什么是“引用赋值”?
当你把一个引用类型变量赋给另一个变量时,两个变量指向同一块堆内存:
- 修改其中一个变量的属性或元素,会影响另一个变量看到的内容;
- 但重新给某个变量赋新对象(如
a = {}),不会影响另一个变量——因为只是改变了它持有的地址,没动原来的内存。
示例:
let obj1 = { name: "Alice" };
let obj2 = obj1; // 复制引用,obj2 和 obj1 指向同一个对象
obj2.name = "Bob";
console.log(obj1.name); // "Bob" ← obj1 也被改了
obj2 = { name: "Charlie" }; // obj2 现在指向新对象
console.log(obj1.name); // "Bob" ← obj1 不受影响
常见引用类型赋值行为
以下类型都遵循相同规则:赋值复制的是引用,不是内容:
- 对象(Object):包括普通对象、Date、RegExp、Error 等实例;
-
数组(Array):
let arr2 = arr1后,push/pop/修改索引都会相互影响; - 函数(Function):函数也是对象,赋值后共享同一函数体(但函数本身不可变,影响主要体现在闭包或 this 绑定场景);
- Map / Set / WeakMap / WeakSet:赋值后增删元素会同步反映;
-
类实例:通过
new MyClass()创建的对象同样按引用赋值。
如何避免意外的“共享修改”?
若需独立副本,必须显式深拷贝或浅拷贝:
-
浅拷贝(只复制第一层):用
Object.assign({}, obj)、展开运算符{...obj}或[...arr]; -
深拷贝(递归复制所有层级):可用
JSON.parse(JSON.stringify(obj))(仅限纯数据,不支持函数、undefined、Date 等),或使用 Lodash 的_.cloneDeep()、结构化克隆(structuredClone(),现代浏览器支持); -
冻结对象防误改:用
Object.freeze(obj)可阻止属性修改(浅冻结)。
注意:null 和 typeof 的小陷阱
null 是原始值(尽管 typeof null === 'object' 是历史 bug),赋值时是值传递,不涉及引用;而 undefined、boolean、number、string、symbol、bigint 都是原始类型,永远值传递。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











