一、浅拷贝概念
浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址。即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址。
二、深拷贝概念
深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
三、浅拷贝和深拷贝的区别
浅拷贝和深拷贝都创建出一个新的对象,但在复制对象属性的时候,行为就不一样。
浅拷贝只复制属性指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,修改对象属性会影响原对象。
但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
四、如何实现一个浅拷贝
function shallowClone(obj) {
const newObj = {};
for (let prop in obj) {
if (obj.hasOwnProperty(prop)) {
newObj[prop] = obj[prop];
}
}
return newObj;
}
// 测试
let originalObject = {
name: 'Alice',
age: 25,
hobbies: ['reading', 'traveling']
};
let shallowCopiedObject = shallowClone(originalObject);
// 修改原始对象的属性
originalObject.hobbies.push('swimming');
// 输出结果
console.log('原始对象:', originalObject);
console.log('浅拷贝对象:', shallowCopiedObject);
shallowClone
函数接受一个对象作为参数,然后遍历对象的属性,通过赋值的方式进行浅拷贝,并返回新的对象。
五、如何实现一个深拷贝
function deepClone(obj) {
const newObj = Array.isArray(obj) ? [] : {};
for (let prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (typeof obj[prop] === 'object' && obj[prop] !== null) {
newObj[prop] = deepClone(obj[prop]); // 递归深拷贝子对象
} else {
newObj[prop] = obj[prop];
}
}
}
return newObj;
}
// 测试
let originalObject = {
name: 'Alice',
age: 25,
hobbies: ['reading', 'traveling']
};
let deepCopiedObject = deepClone(originalObject);
// 修改原始对象的属性
originalObject.hobbies.push('swimming');
// 输出结果
console.log('原始对象:', originalObject);
console.log('深拷贝对象:', deepCopiedObject);
deepClone
函数接受一个对象作为参数,然后遍历对象的属性。如果属性的值是对象类型,则递归调用deepClone
函数进行深拷贝,否则直接赋值。最终返回一个深度拷贝的新对象。
六、浅拷贝的实现方式
1、Object.assign
Object.assign
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象。它只会拷贝源对象自身的属性,不会拷贝继承的属性。
const source = { name: 'Alice', age: 25 };
const target = Object.assign({}, source);
console.log(target);
2、slice()
slice()
方法返回一个新的数组对象,这个对象是一个由 begin
和 end
决定的原数组的浅拷贝。原数组不会被改变。
const originalArray = [1, 2, 3, 4, 5];
const copiedArray = originalArray.slice();
console.log(copiedArray);
3、concat()
concat()
方法用于连接两个或多个数组。该方法不会改变现有数组,而是返回一个新数组。
const array1 = [1, 2];
const array2 = [3, 4];
const concatenatedArray = array1.concat(array2);
console.log(concatenatedArray);
4、拓展运算符
拓展运算符是ES6引入的一种语法,用于展开数组或对象。在浅拷贝中,拓展运算符可以用来创建新的数组或对象,并复制原始数据,但仍然是浅拷贝。
const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];
console.log(copiedArray); // 输出: [1, 2, 3]
const originalObject = { name: 'Alice', age: 25 };
const copiedObject = { ...originalObject };
console.log(copiedObject);
七、深拷贝的实现方式
1、_.cloneDeep()
_.cloneDeep()
方法来自于lodash
库,用于创建一个深度拷贝的对象,递归地复制所有属性。
const originalObject = { name: 'Alice', age: 25, hobbies: ['reading', 'traveling'] };
const deepCopiedObject = _.cloneDeep(originalObject);
console.log(deepCopiedObject);
2、jQuery.extend()
jQuery.extend()
方法是jQuery库中的一个方法,用于将一个或多个对象的内容合并到目标对象中,实现深拷贝。
const originalObject = { name: 'Alice', age: 25 };
const deepCopiedObject = $.extend(true, {}, originalObject);
console.log(deepCopiedObject);
3、JSON.stringify()
JSON.stringify()
方法将一个JavaScript值(对象或数组)转换为一个JSON字符串,利用JSON的序列化和反序列化实现深拷贝。
const originalObject = { name: 'Alice', age: 25 };
const deepCopiedObject = JSON.parse(JSON.stringify(originalObject));
console.log(deepCopiedObject);
4、循环递归
循环递归是一种常见的实现深拷贝的方法,通过递归遍历对象的每个属性,并逐层复制,实现完全独立的深拷贝。
function deepClone(obj) {
const newObj = Array.isArray(obj) ? [] : {};
for (let prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (typeof obj[prop] === 'object' && obj[prop] !== null) {
newObj[prop] = deepClone(obj[prop]); // 递归深拷贝子对象
} else {
newObj[prop] = obj[prop];
}
}
}
return newObj;
}
const originalObject = { name: 'Alice', age: 25 };
const deepCopiedObject = deepClone(originalObject);
console.log(deepCopiedObject);