在JavaScript中,我们经常需要将一个对象或数组复制到另一个变量中。在这个过程中,拷贝的方式可以分为深拷贝和浅拷贝两种。深拷贝是创建一个新的对象或数组,并将原始数据结构中的所有值都复制到新的数据结构中。浅拷贝则只是创建了一个新的变量,但是原始数据结构中的引用仍然指向同一个地址。
浅拷贝
浅拷贝是一种非常常见和简单的拷贝方式,它仅仅是将原始对象或数组的引用复制给新的变量。当修改其中一个变量的值时,另一个变量也会随之改变。
在JavaScript中,我们可以使用Object.assign()
和扩展运算符(...
)来进行浅拷贝。
// 浅拷贝示例
let obj1 = {name: "John", age: 25};
let obj2 = Object.assign({}, obj1);
// or let obj2 = {...obj1};
obj2.name = "Jane";
console.log(obj1); // {name: "John", age: 25}
console.log(obj2); // {name: "Jane", age: 25}
let arr1 = [1, 2, 3, 4];
let arr2 = [...arr1];
// or let arr2 = arr1.slice();
arr2.push(5);
console.log(arr1); // [1, 2, 3, 4]
console.log(arr2); // [1, 2, 3, 4, 5]
如上所示,在浅拷贝中,修改obj2
的属性或添加新元素到arr2
并不会影响到原始对象obj1
和原始数组arr1
。
深拷贝
相较于浅拷贝,深拷贝会创建一个全新的对象或数组,并将原始数据结构中的所有值都复制给新的数据结构。当修改其中一个变量的值时,另一个变量不会受到任何影响。
深拷贝可以通过递归地复制每个属性或元素来实现,或者借助JSON序列化和反序列化来实现。
递归实现深拷贝
// 深拷贝示例(递归实现)
function deepClone(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
let clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}
let obj1 = {name: "John", age: 25, hobbies: ["reading", "coding"]};
let obj2 = deepClone(obj1);
obj2.hobbies.push("painting");
console.log(obj1); // {name: "John", age: 25, hobbies: ["reading", "coding"]}
console.log(obj2); // {name: "John", age: 25, hobbies: ["reading", "coding", "painting"]}
let arr1 = [1, 2, {name: "John"}, [3, 4]];
let arr2 = deepClone(arr1);
arr2[2].name = "Jane";
console.log(arr1); // [1, 2, {name: "John"}, [3, 4]]
console.log(arr2); // [1, 2, {name: "Jane"}, [3, 4]]
通过递归调用deepClone
函数,我们可以确保每个属性或元素都会被复制到新的对象或数组中。
JSON序列化与反序列化实现深拷贝
// 深拷贝示例(JSON序列化与反序列化实现)
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
let obj1 = {name: "John", age: 25, hobbies: ["reading", "coding"]};
let obj2 = deepClone(obj1);
obj2.hobbies.push("painting");
console.log(obj1); // {name: "John", age: 25, hobbies: ["reading", "coding"]}
console.log(obj2); // {name: "John", age: 25, hobbies: ["reading", "coding", "painting"]}
let arr1 = [1, 2, {name: "John"}, [3, 4]];
let arr2 = deepClone(arr1);
arr2[2].name = "Jane";
console.log(arr1); // [1, 2, {name: "John"}, [3, 4]]
console.log(arr2); // [1, 2, {name: "Jane"}, [3, 4]]
使用JSON的JSON.stringify()
和JSON.parse()
方法,我们可以将对象或数组转换为JSON字符串,然后再将其解析为新的对象或数组。这种方法可以处理大部分简单的数据结构,但是无法处理循环引用(对象互相引用导致的死循环)的情况。
总结
在JavaScript中,深拷贝和浅拷贝是常见的操作。理解它们的区别和如何实现它们可以帮助我们在处理对象或数组时更加灵活地复制和操作数据。浅拷贝适用于简单的数据结构和对原始数据没有修改的场景,而深拷贝则适用于需要创建全新数据结构的场景。根据具体的需求可以选择合适的拷贝方式。
本文来自极简博客,作者:倾城之泪,转载请注明原文链接:JavaScript中的深拷贝和浅拷贝