JavaScript 数组深拷贝与浅拷贝详解
本文详解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
}
文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
相关标签:
