关于JavaScript浅拷贝的困惑:修改拷贝数组为何影响原数组?
JavaScript浅拷贝的核心逻辑解析
先明确核心结论:浅拷贝只复制「第一层结构」——对于基本类型是值复制,对于引用类型(比如对象),复制的是指向该对象的引用地址,而非对象本身。下面结合你的三个示例逐一拆解:
示例1:数组元素为基本类型
const a = [1,2,3] const b = [...a] // 浅拷贝 b[0] = 9 console.log(a) // [1,2,3] console.log(b) // [9,2,3]
数组a的元素都是基本类型(数字),浅拷贝时b会把每个元素的值完整复制一份。修改b[0]只是修改了b数组内的独立值,和a数组的元素没有关联,所以a不受影响。
示例2:重新赋值拷贝数组的对象元素
const a = [{name:"John"},{name:"George"}]; const b = [...a]; b[0] = {name:"Oliver"} console.log(a) // [ { name: 'John' }, { name: 'George' } ] console.log(b); // [ { name: 'Oliver' }, { name: 'George' } ]
浅拷贝后,b[0]原本和a[0]指向同一个对象,但这里我们直接给b[0]重新赋值了一个全新的对象——相当于把b[0]的引用地址替换成了新对象的地址,和a[0]的引用地址彻底解绑。所以修改后a的元素还是原来的对象,不受影响。
示例3:修改拷贝数组元素的对象属性
const a = [{name:"John"},{name:"George"}]; const b = [...a]; b[0].age = 21 console.log(a); //[ { name: 'John', age: 21 }, { name: 'George' } ] console.log(b); // [ { name: 'John', age: 21 }, { name: 'George' } ]
浅拷贝只复制了数组第一层的引用,b[0]和a[0]依然指向内存中同一个对象。当你修改b[0].age时,本质是在操作这个共享的对象本身,而非修改b[0]的引用地址——所以a[0]的属性也会跟着变化,因为它们指向的是同一个对象。
总结
- 浅拷贝对基本类型是独立的值复制,修改拷贝后的元素不会影响原数组;
- 对引用类型,拷贝的是引用地址,原数组和拷贝数组的元素共享同一个对象;
- 直接给拷贝数组的元素重新赋值,是替换引用地址,不会影响原数组;但修改引用类型元素的内部属性,会影响原数组,因为操作的是同一个对象实体。
内容的提问来源于stack exchange,提问作者Kaan Topal
相关产品推荐
相关产品推荐

