一、浅拷贝
浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址。
浅拷贝是指创建一个新对象,这个对象有着原始对象属性的副本。
在浅拷贝中,如果原始对象中的属性是引用类型数据(比如数组、对象等),那么新对象中对应的属性会复制一个指向原始对象中相同的引用。
因此,当修改新对象中的引用类型属性时,原始对象中的对应属性也会被修改。
1.1、例子一 for in
function shallowClone(obj) {
const newObj = {};
for(let prop in obj) {
if(obj.hasOwnProperty(prop)){
newObj[prop] = obj[prop];
}
}
return newObj;
}
1.2、例子二 Object.assign({}, originalObj)
例如,以下代码展示了一个浅拷贝的例子:
let originalObj = {
name: "John",
age: 30,
hobbies: ["reading", "traveling"]
};
let newObj = Object.assign({}, originalObj);
newObj.hobbies.push("cooking");
console.log(originalObj.hobbies); // Output: ["reading", "traveling", "cooking"]
console.log(newObj.hobbies); // Output: ["reading", "traveling", "cooking"]
在上面的代码中,我们使用Object.assign()
方法创建了一个新对象newObj
,该对象是originalObj
的浅拷贝。
当我们修改newObj
的hobbies
属性时,originalObj
中对应的属性也被同时修改了。
这是因为newObj
和originalObj
中的hobbies
属性引用的是同一个数组对象。
二、深拷贝
深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
深拷贝是指在内存中将一个对象完整复制一份,包括其所有的属性和子属性。手动实现深拷贝可以使用递归来遍历对象的每个属性和子属性,并复制它们的值到新的对象中。
当涉及到深拷贝时,以下是一个示例来手动实现 JavaScript
中的深拷贝:
function deepCopy(obj) {
// 判断传入的参数是否为对象或数组
if (typeof obj !== 'object' || obj === null) {
return obj; // 如果是基本类型直接返回
}
let clone;
// 根据传入的对象类型创建新的对象或数组
if (Array.isArray(obj)) {
clone = [];
} else {
clone = {};
}
// 遍历原对象的属性并递归进行深拷贝
for (let key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
clone[key] = deepCopy(obj[key]);
}
}
return clone;
}
// 示例
const obj1 = {
name: 'John',
age: 30,
hobbies: ['reading', 'writing'],
address: {
street: '123 Main St',
city: 'New York'
}
};
const obj2 = deepCopy(obj1);
obj2.name = 'Jane';
obj2.hobbies.push('painting');
obj2.address.city = 'Los Angeles';
console.log(obj1); // { name: 'John', age: 30, hobbies: [ 'reading', 'writing' ], address: { street: '123 Main St', city: 'New York' } }
console.log(obj2); // { name: 'Jane', age: 30, hobbies: [ 'reading', 'writing', 'painting' ], address: { street: '123 Main St', city: 'Los Angeles' } }
在上面的示例中,deepCopy
函数用于手动实现深拷贝。通过调用 deepCopy(obj1)
,我们可以将 obj1
完整地复制到 obj2
中,并且对 obj2
的修改不会影响到 obj1
。
三、总结
在JavaScript
中,浅拷贝和深拷贝是两种常见的对象复制方式,它们有着不同的特点和适用场景。
3.1、浅拷贝
- 创建一个新对象,新对象的属性值是原始对象属性的副本。
- 如果原始对象的属性是基本数据类型(如字符串、数字、布尔值等),则直接复制属性值。
- 如果原始对象的属性是引用类型数据(如数组、对象等),则复制的是对原始对象属性的引用。
- 当修改新对象中的引用类型属性时,原始对象中的对应属性也会被修改。
- 常见的浅拷贝方法包括
Object.assign()
、扩展运算符(...
)和Array.slice()
等。
3.2、深拷贝
- 创建一个新对象,新对象的属性值是原始对象属性的完全独立副本。
- 无论原始对象的属性是基本数据类型还是引用类型数据,都会被完全复制一份,包括嵌套的对象和数组。
- 修改新对象中的任何属性,不会影响原始对象中对应的属性。
- 实现深拷贝的常见方法包括递归遍历、
JSON.parse(JSON.stringify())
、第三方库(如Lodash
的cloneDeep()
方法)等。
选择使用浅拷贝还是深拷贝要根据具体的需求场景来决定:
- 如果你只需要复制对象的第一层属性,并且不关心对应属性的修改是否会影响原始对象,那么浅拷贝就足够了。
- 如果你需要完全独立的新对象,并确保对新对象的修改不会影响原始对象,那么深拷贝是更好的选择。
需要注意的是,深拷贝可能会导致性能上的损耗,特别是当对象很大或嵌套层级很深时。因此,在处理大型复杂对象时,要考虑是否真正需要深拷贝,以避免不必要的性能开销。
四、最后
本人每篇文章都是一字一句码出来,希望大佬们多提提意见。顺手来个三连击,点赞👍收藏💖关注✨。创作不易,给我打打气,加加油☕