JavaScript数组复制详解:浅拷贝与深拷贝实现
作者:异步漫步时间:2026-10-26 12:52:46浏览:381
本文详细解析JavaScript中数组复制的两种主要方式:浅拷贝与深拷贝。通过concat、slice、扩展运算符及Object.assign实现浅拷贝,并探讨JSON.parse、递归函数及lodash库在深拷贝中的应用,重点分析各方法的局限性与适用场景。
在JavaScript开发中,数组复制是常见需求。由于Array属于引用类型,若仅通过arrA=arrB进行简单赋值,并未创建新数组,而是让两个变量指向同一内存地址。此时修改任一变量,另一个也会随之改变,这通常不符合预期结果。
var arr = [1, 2, 3];
var newArr = arr;
arr.push(4);
console.log(newArr1); // [1, 2, 3, 4]接下来介绍数组的浅复制方法。
这种方法适用于结构简单的数组,即数组内部不包含嵌套对象或嵌套数组的情况。
方法一:使用concat()。
- concat()函数用于连接两个或多个数组。
- 该函数不会修改现有数组,而是返回一个新数组,其中包含被连接数组的值。
var arr = [1, 2, 3];
var newArr = arr.concat();
arr.push(4);
console.log(newArr); // [1, 2, 3]方法二:使用slice()。
- slice()函数返回一个新数组,包含从原数组中选定的元素。
- 该函数从指定的start参数开始选取元素,并在给定的end参数处结束(不包含end位置的元素)。
- slice()函数同样不会改变原始数组。
var arr = [1, 2, 3];
var newArr = arr.slice();
arr[0] = 10;
console.log(arr);// [10, 2, 3]
console.log(newArr);// [1, 2, 3]方法三:使用扩展运算符。
var arr = [1, 2, 3];
var [ ...newArr ] = arr;
arr[0] = 10;
console.log(arr); // [10, 2, 3]
console.log(newArr);// [1, 2, 3]方法四:使用Object.assign()。
var arr = [1, 2, 3];
var newArr = Object.assign([], arr);
arr[0] = 10;
console.log(arr);// [10, 2, 3]
console.log(newArr);// [1, 2, 3]需要注意的是,如果数组元素包含对象或数组,上述四种浅拷贝方法仅会拷贝引用。因此,修改其中一个数组的元素,另一个数组的对应元素也会发生变化。
例如:
var arr = [ { a: 1 }, [ 1, 2 ], 3 ];
let newArr = arr.concat();
arr[0].a = 2;
console.log(arr); // [ { a: 2 }, [ 1, 2 ], 3 ]
console.log(newArr);// [ { a: 2 }, [ 1, 2 ], 3 ] 值被影响接下来介绍深复制方法。
深复制可以完全拷贝数组,即使内部嵌套了对象或数组,新旧数组之间也不会相互影响。
方法一:使用JSON.parse(JSON.stringify(arr))。
var arr = [ { a: 1 }, [ 1, 2 ], 3 ];
// let newArr = JSON.parse(JSON.stringify(arr));
let newArr = arr.concat();
arr[0].a = 2;
console.log(arr); // [ { a: 2 }, [ 1, 2 ], 3 ]
console.log(newArr);// [ { a: 1 }, [ 1, 2 ], 3 ]然而,该方法存在明显的局限性。
- 它会忽略undefined类型的值。
- 它也会忽略symbol类型的值。
- 该方法无法序列化函数。
- 此外,它不能处理包含循环引用的对象。
下面通过一个示例说明:
let a = {
age: undefined,
sex: Symbol('male'),
jobs: function() {},
name: 'sun'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "sun"}方法二:通用深拷贝方法(适用于数组或对象)。
在拷贝过程中判断属性值的类型,若为对象,则继续递归调用深拷贝函数(此为简易版实现)。
var deepCopy = function(obj) {
// 判断是否是对象
if (typeof obj !== 'object') return;
// 判断obj类型,根据类型新建一个对象或者数组
var newObj = obj instanceof Array ? [] : {}
// 遍历对象,进行赋值
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
let val = obj[key];
// 判断属性值的类型,如果是对象,递归调用deepCopy
newObj[key] = typeof val === 'object' ? deepCopy(val) : val
}
}
return newObj
}方法三:利用lodash库提供的深拷贝函数。
_.cloneDeep(value)其中value参数即为需要深拷贝的值。
简单使用示例如下:
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false在Vue项目中的使用方式。
首先进行安装。
npm i --save lodash然后在main.js文件中引入。
import _ from 'lodash';
Vue.prototype._ = _;最后在实际代码中使用。
let newObj = this._.cloneDeep(oldObj)总结。
以上内容为个人经验分享,旨在提供参考,欢迎大家支持本站。
作者最新文章
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
相关标签:
