JavaScript基础篇-浅拷贝与深拷贝

260 阅读2分钟

前言

“拷贝”,字面意思就是复制,所以 JavaScript 的拷贝就是将一个变量赋值给另外一个变量,在 JavaScript 中有两种拷贝类型 浅拷贝和深拷贝,两者的区别主要体现在引用类型上面

浅拷贝与深拷贝的区别

浅拷贝和深拷贝都是将一个变量赋值给另外一个变量,不同的是,在使用引用类型进行赋值的时候,通过 浅拷贝 赋值的变量会影响到 原始变量 的值,而 深拷贝 则不会。由于引用类型是存储的是地址而非值(可以参考我上一篇文章 JavaScript基础篇-数据类型),所以在修改引用变量的值时是在修改它们存储在堆中的值,但是由于两个变量都是存储的地址,所以两个变量都会发生变化。

// 通过浅拷贝的例子
let obj1 = {
    name: 'zhangsan'
}
let obj2 = obj1
obj2.name = 'lisi'
console.log(obj1.name) // lisi
console.log(obj2.name) // lisi

深拷贝的方式(不考虑堆栈溢出)

  • JSON转换 主要是使用 JSON 的两个方法 stringify() 和 parse(),先使用 JSON.stringify() 将原有对象转换成 JSON 类型,然后在使用 JSON.parse() 将其转回。该方法存在一定的缺陷:
    1. 如果对象里有函数,函数无法被拷贝下来
    2. 无法拷贝对象原型链上的属性和方法
let obj1 = {
    name: 'zhangsan'
}
let obj2 = JSON.parse(JSON.stringify(obj1))
obj2.name = 'lisi'
console.log(obj1.name) // lisi
console.log(obj2.name) // zhangsan
  • 递归的方式 使用递归的方式把对象中的对象全部遍历完,在遍历中遇到对象就新开辟一块内存进行存储
// 深拷贝
function deepCopy(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return obj;
    }
    let result = {};
    if (obj instanceof Array) { result = []; }
    for(var key in obj) {
         // Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
        if(obj.hasOwnProperty(key)) { result[key] = deepCopy(obj[key]); }
    }
    return result;
}
let obj1 = {
    name: 'zhangsan'
}
let obj2 = deepCopy(obj1)
obj2.name = 'lisi'
console.log(obj1.name) // lisi
console.log(obj2.name) // zhangsan