JavaScript 数组深拷贝与浅拷贝详解

作者:纸飞机时间:2026-10-23 08:03:48浏览:204

本文详解JavaScript中数组的浅拷贝与深拷贝机制。由于数组是引用类型,直接赋值仅复制内存指针。展开运算符...实现浅拷贝,无法处理嵌套数组;JSON.parse(JSON.stringify())可深拷贝但存在局限。推荐使用Lodash的cloneDeep或手写递归函数实现真正的深拷贝,确保嵌套数据独立。

数组拷贝类型概述

数组拷贝主要分为两种类型:浅拷贝与深拷贝。浅拷贝仅复制数组的第一层元素,内部嵌套对象仍保持引用关系。若需完全独立且包含嵌套结构的数组副本,必须采用深拷贝策略。常见的实现方式包括利用JSON序列化方法或引入Lodash库中的专用工具。


const numbers = [1, [2], [3, [4]], 5];
// Using JavaScript
JSON.parse(JSON.stringify(numbers));
// Using Lodash
_.cloneDeep(objects);

引用类型基础

在JavaScript中,数组属于引用类型。

理解这两种拷贝差异的基础在于掌握引用类型的概念。与number、string等原始类型不同,数组作为引用类型,其赋值操作并非复制实际数据,而是将原数组在内存中的地址赋给新变量。

值类型拷贝机制

值类型的拷贝机制相对直观。

创建值类型的副本时,修改副本的值不会波及原始变量,反之亦然。这种双向独立性使得值类型拷贝操作安全且易于预测。


let value = 3;
let valueCopy = value; // create copy
console.log(valueCopy); // 3
// Change valueCopy
valueCopy = 100
console.log(valueCopy); // 100
// ✅ Original NOT affected 
console.log(value); // 3

引用类型拷贝特性

引用类型的拷贝行为则较为特殊,容易引发意外结果。

采用与值类型相同的赋值逻辑处理数组时,会出现非预期的共享现象。


let array = [1,2,3];
let arrayCopy = array; // create copy
console.log(arrayCopy); // [1,2,3];
// Change 1st element of the array
arrayCopy[0] = '👻';
console.log(arrayCopy); // [ '👻', 2, 3 ]
// ❌Original got affected
console.log(array); // [ '👻', 2, 3 ]

原始数组受影响的原因在于:我们实际拷贝的只是指向内存空间的指针,而非数据本身。引用类型不直接包含值,而是存储指向内存中实际数据的地址指针。

引用类型拷贝解决方案

解决引用类型拷贝问题的核心在于复制实际值而非指针。

通过特定的技术手段,可以实现对引用类型数据的真正独立副本创建。


let array = [1,2,3];
let arrayCopy = [...array]; // create TRUE copy
console.log(arrayCopy); // [1,2,3];
// Change 1st element of the array
arrayCopy[0] = '👻';
console.log(arrayCopy); // [ '👻', 2, 3 ]
// ✅ Original NOT affected 
console.log(array); // [ 1, 2, 3 ]

浅拷贝与深拷贝对比

展开运算符(...)常用于数组拷贝,但这仅属于浅拷贝范畴。

当数组包含嵌套结构或多维数据时,展开运算符无法实现深层独立。修改副本中嵌套元素的值,会导致原始数组中对应的嵌套部分同步改变。


let nestedArray = [1, [2], 3];
let arrayCopy = [...nestedArray];
// Make some changes
arrayCopy[0] = '👻'; // change shallow element
arrayCopy[1][0] = '💩'; // change nested element
console.log(arrayCopy); // [ '👻', [ '💩' ], 3 ]
// ❌ Nested array got affected
console.log(nestedArray); // [ 1, [ '💩' ], 3 ]

虽然浅拷贝对数组第一层元素的操作表现正常,但修改嵌套数组元素会同时影响原始数组。为解决这一嵌套数据共享问题,必须引入深拷贝机制。


let nestedArray = [1, [2], 3];
let arrayCopy = JSON.parse(JSON.stringify(nestedArray));
// Make some changes
arrayCopy[0] = '👻'; // change shallow element
arrayCopy[1][0] = '💩'; // change nested element
console.log(arrayCopy); // [ '👻', [ '💩' ], 3 ]
// ✅ Nested array NOT affected
console.log(nestedArray); // 1, [ 2 ], 3 ]

除了使用内置方法,是否可以通过手写代码实现深拷贝引用类型的方法?


const deepClone = obj => {
const isObject = args => (typeof args === 'object' || typeof args === 'function') && typeof args !== null
if (!isObject) throw new Error('Not Reference Types')
let newObj = Array.isArray(obj) ? [...obj] : { ...obj }
Reflect.ownKeys(newObj).map(key => {
newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
})
return newObj
}

文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,

作者最新文章