目录
JavaScript数据拷贝类型
浅拷贝
深拷贝
举例:
浅拷贝
数组
对象
深拷贝
lodash cloneDeep使用示例
自定义深拷贝方法示例
JSON.parse() 和 JSON.stringify()使用示例
数组可以使用Array.prototype.slice()方法
对象可以使用Object.assign()方法
数组和对象都可以使用第三方库lodash 的 _.cloneDeep()方法或者自己封装
或者JSON.parse() 和 JSON.stringify()
JavaScript 的 Array.prototype.slice()
方法对于数组来说是浅拷贝(shallow copy)。
当使用 slice()
方法时,它会创建一个新的数组,包含从开始到结束(不包括结束)的元素。然而,这个方法创建的新数组中的元素是原数组中元素的引用,而不是这些元素的副本。这意味着如果原数组中的元素是对象,那么新数组和对象仍然会引用相同的对象。因此,对于这种情况,slice()
实现的是浅拷贝。
例如:
let arr1 = [{ a: 1 }, { b: 2 }];
let arr2 = arr1.slice();
arr2[0].a = 2;
arr2[1] = { b: 3 };
console.log(arr1); // 输出:[{ a: 2 }, { b: 2 }]
console.log(arr2); // 输出:[{ a: 2 }, { b: 3 }]
slice无法实现深拷贝例子
可以使用 Object.assign()
方法实现浅拷贝:
let original = {a: 1, b: 2, c: {d: 3}};
let copy = Object.assign({}, original);
_.cloneDeep()
是 Lodash 库中的一个函数,用于执行深拷贝(deep clone)操作。该函数会创建一个新的对象,复制源对象(source object)的所有值,包括嵌套的对象和数组。与浅拷贝(shallow clone)不同,深拷贝会递归地复制对象的所有层级,而不仅仅是第一层。
使用
_.cloneDeep()
可以确保源对象不会被修改,因为所有的值都被复制到了新的对象中。这在处理复杂数据结构时特别有用,尤其是当你不想改变原始数据,但又需要对其进行操作时
深拷贝例子
const _ = require('lodash');
const originalObject = {
name: 'John',
age: 30,
address: {
city: 'New York',
country: 'USA'
}
};
const clonedObject = _.cloneDeep(originalObject);
console.log(clonedObject);
// 输出:{ name: 'John', age: 30, address: { city: 'New York', country: 'USA' } }
// 修改克隆对象的属性值
clonedObject.name = 'Jane';
clonedObject.address.city = 'Los Angeles';
console.log(originalObject);
// 输出:{ name: 'John', age: 30, address: { city: 'New York', country: 'USA' } }
console.log(clonedObject);
// 输出:{ name: 'Jane', age: 30, address: { city: 'Los Angeles', country: 'USA' } }
function getObjType(obj) {
var toString = Object.prototype.toString;
var map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
};
return map[toString.call(obj)];
};
function cloneDeep(data) {
var type = getObjType(data);
var obj;
if (type === 'array') {
obj = [];
} else if (type === 'object') {
obj = {};
} else {
// 已到达最后一个层级
return data;
}
if (type === 'array') {
for (var i = 0, len = data.length; i < len; i++) {
data[i] = function () {
if (data[i] === 0) {
return data[i];
}
return data[i] || {};
}();
delete data[i].$parent;
obj.push(cloneDeep(data[i]));
}
} else if (type === 'object') {
for (var key in data) {
delete data.$parent;
obj[key] = cloneDeep(data[key]);
}
}
return obj;
};
但需要注意的是,这种方法只适用于可序列化的对象,如果对象中包含函数、undefined 或者 symbol 类型,或者存在循环引用,则这种方法不能使用。
对于更复杂的深拷贝需求,可以使用到递归或者其他库如 lodash 的 _.cloneDeep() 方法。