js的浅拷贝和深拷贝

181 阅读2分钟

一、浅拷贝和深拷贝的定义

浅拷贝:浅拷贝只是拷贝一层更深层次对象级别的只拷贝引用。

深拷贝:深拷贝拷贝多层,每一级别的数据都会拷贝。

二、浅拷贝和深拷贝的区别

浅拷贝和深拷贝都创建出一个新的对象,但在复制对象属性的时候,行为就不一样

1. 浅拷贝只复制属性指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,修改对象属性会影响原对象

2. 深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象

三、浅拷贝的实现

  1. for···in只循环第一层
// 只复制第一层的浅拷贝
        function simpleCopy(obj1) {
            var obj2 = Array.isArray(obj1) ? [] : {};
            for (let i in obj1) {
                obj2[i] = obj1[i];
            }
            return obj2;
        }
        var obj1 = {
            a: 1,
            b: 2,
            c: {
                d: 3
            }
        }
        var obj2 = simpleCopy(obj1);
        obj2.a = 3;
        obj2.c.d = 4;
        console.log(obj1.a); // 1
        console.log(obj2.a); // 3
        console.log(obj1.c.d); // 4
        console.log(obj2.c.d); // 4
  1. Object.assign方法
var obj = {
    a: 1,
    b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a) // 3
  1. 直接用=赋值
let a=[0,1,2,3,4],
    b=a;
console.log(a===b);
a[0]=1;
console.log(a,b);
  1. 拓展运算符
const fxArr = ["One", "Two", "Three"]
const fxArrs = [...fxArr]
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]

四、深拷贝的实现

  1. 采用递归去拷贝所有层级属性
function deepClone(obj){
    let objClone = Array.isArray(obj)?[]:{};
    if(obj && typeof obj==="object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                //判断ojb子元素是否为对象,如果是,递归复制
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}    
let a=[1,2,3,4],
    b=deepClone(a);
a[0]=2;
console.log(a,b);
  1. 利用 JSON 对象实现深拷贝
// 深拷贝拷贝多层, 每一级别的数据都会拷贝.
var obj = {
    id: 1,
    name: 'andy',
    msg: {
        age: 18
    },
    color: ['pink', 'red']
};

// 2. 利用 JSON 对象
function deepCopy(obj) {
    let _obj = JSON.stringify(obj);
    let newObj = JSON.parse(_obj);
    return newObj;
}

let newObj = deepCopy(obj);
newObj.msg.age = 22;
console.log(newObj);  //  newObj.msg.age = 22
console.log(obj);  // obj.msg.age 还是等于 18 没有改变

五、总结

前提为拷贝类型为引用类型的情况下:

  • 浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址
  • 深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址