javascript中引用类型赋值/传参是“指针共享”,需用浅拷贝(如展开运算符)或深拷贝(如structuredclone)避免修改原数据,函数应明确职责、避免直接修改参数。

JavaScript 中没有真正的“指针”,但引用类型(如对象、数组、函数)在赋值或传参时,实际传递的是对内存中同一堆地址的引用,这常被通俗称为“指针共享”。要避免意外修改原数据,关键在于创建独立副本,而不是复用引用。
理解什么是引用共享
当你把一个对象赋给另一个变量,或作为参数传入函数时,JS 并没有复制整个对象,而是让新变量指向同一块内存:
let obj1 = { name: "Alice" };
let obj2 = obj1; // obj2 和 obj1 指向同一个对象
obj2.name = "Bob";
console.log(obj1.name); // "Bob" —— obj1 也被改了
这不是 bug,是 JS 的设计机制。所有引用类型(Object、Array、Date、RegExp、Function 等)都如此。
浅拷贝:适用于一层结构
如果对象只有基本类型属性(无嵌套对象),可用浅拷贝切断顶层引用:
-
展开运算符:
const copy = { ...original };或[...arr] -
Object.assign():
const copy = Object.assign({}, original); -
Array.from() / slice()(数组):
const newArr = Array.from(oldArr);
⚠️ 注意:浅拷贝只复制第一层。若原对象含嵌套对象,嵌套部分仍共享引用。
深拷贝:彻底隔离嵌套结构
当数据有深层嵌套(如对象里有对象、数组里有对象),需深拷贝:
-
JSON 方法(简单场景):
JSON.parse(JSON.stringify(obj))—— 快速但有局限:会丢弃函数、undefined、Symbol、Date、RegExp、循环引用,且 Date 变成字符串 -
structuredClone()(推荐,现代环境):
const deepCopy = structuredClone(original);—— 原生支持大多数类型(包括 Map、Set、Date、RegExp),不支持函数和 DOM 节点,且需浏览器/Node.js 版本支持(Node ≥17.0,主流浏览器已支持) -
Lodash 的 cloneDeep():
_.cloneDeep(obj)—— 兼容性好,功能全面,适合复杂旧项目
函数传参时的实践建议
在函数内部避免直接修改传入的引用类型参数:
- 明确函数职责:如果是“计算型”函数(如
getFullName(user)),应返回新值,不修改原对象 - 如需修改,先深拷贝再操作:
const safeUser = structuredClone(user); safeUser.name = "New"; return safeUser; - 使用
const声明参数可防误重赋值,但不阻止属性修改(因为 const 限制的是绑定,不是值的可变性)
不复杂但容易忽略:多数时候你并不需要深拷贝——先问自己:“我是否真的要保留原始数据不变?” 若只是读取或临时组装,浅拷贝甚至无需拷贝即可安全使用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











