返回

javascript 深浅拷贝探秘

前端

认识深拷贝

在javascript中,变量存储的是值的引用,而不是值本身,这也就是为什么变量之间的赋值操作,实际上是对值的引用的复制,而不是对值本身的复制。

举个例子:

let a = {
    name: '张三',
    age: 18
};

let b = a; // 将a的引用赋值给b

console.log(a === b); // 输出true,说明a和b指向同一个对象

在这个例子中,当我们将a的引用赋值给b时,实际上并没有复制a对象本身,而是将a对象的引用复制给了b,所以ab指向同一个对象,a === btrue

当我们对ab对象进行修改时,另一个对象也会受到影响,因为它们指向同一个对象。

a.name = '李四';

console.log(a.name); // 输出'李四'
console.log(b.name); // 输出'李四'

这就是浅拷贝,它只复制对象本身,而不复制对象引用的值。

实现深拷贝

深拷贝是复制一个对象的所有属性,包括属性值、子对象以及数组,并创建一个全新的对象,与原始对象没有任何引用关系。

实现深拷贝有以下几种方法:

1. 使用JSON.parse()JSON.stringify()

这种方法利用了JSON的序列化和反序列化机制来实现深拷贝,具体步骤如下:

let a = {
    name: '张三',
    age: 18,
    hobby: ['篮球', '足球', '乒乓球']
};

let b = JSON.parse(JSON.stringify(a));

console.log(a === b); // 输出false,说明a和b指向不同的对象
console.log(a.hobby === b.hobby); // 输出false,说明a.hobby和b.hobby指向不同的数组

2. 使用递归

这种方法通过递归遍历对象,并复制对象的所有属性值,包括子对象和数组,具体步骤如下:

function deepCopy(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return obj;
    }

    let result = Array.isArray(obj) ? [] : {};

    for (let key in obj) {
        result[key] = deepCopy(obj[key]);
    }

    return result;
}

let a = {
    name: '张三',
    age: 18,
    hobby: ['篮球', '足球', '乒乓球']
};

let b = deepCopy(a);

console.log(a === b); // 输出false,说明a和b指向不同的对象
console.log(a.hobby === b.hobby); // 输出false,说明a.hobby和b.hobby指向不同的数组

3. 使用Object.assign()

这种方法使用Object.assign()方法来实现深拷贝,具体步骤如下:

let a = {
    name: '张三',
    age: 18,
    hobby: ['篮球', '足球', '乒乓球']
};

let b = Object.assign({}, a);

console.log(a === b); // 输出false,说明a和b指向不同的对象
console.log(a.hobby === b.hobby); // 输出false,说明a.hobby和b.hobby指向不同的数组

总结

深拷贝和浅拷贝是javascript中非常重要的概念,理解它们的原理和区别,可以帮助你更好地理解javascript的内存机制,并编写出更加健壮的代码。

在实际开发中,我们经常需要对对象进行深拷贝,以避免对原始对象造成意外的修改。