JS克隆总结 | 8月更文挑战

158 阅读2分钟

这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战

js克隆分为深克隆和浅克隆,可以直接复制的是浅克隆,不可以直接复制的是深克隆。

一、浅克隆

表示直接赋值后,再修改原数据,新对象不会产生变化,就是浅克隆,例如基本类型中String,Number,float,boolean等,可以直接赋值后也不会变化。

//例如
let a = '123';
let a1 = 'hi cl'
let b = a;
let b1 = a1;
console.log(b);//'123'
console.log(b1);'hi cl'

一、深克隆

克隆对象是引用类型,直接复制可能会丢失值,所以不能直接复制,这就要用到深克隆,不然在开发过程中会产生很多问题。

let a = [1,2,3];
let b = a;
a.pop();
console.log(a);//[1,2]
console.log(b);//[1,2]

这里示例的a修改后b也跟着修改了,引用类型是通过地址的方式赋值,说明a和b指向的是同一个地址,导致他们其中一个修改后另一个也修改了,下面说几种修改方式:

1、使用**JSON.stringify()**把js对象序列化(JSON字符串),再使用JSON.parse来反序列化,还原parse过的对象。

let cloneObj = JSON.parse(JSON.stringify(oldObj));//常用的克隆方式

缺点:

1)不能实现函数,正则,时间之类的克隆,如果对象里有时间或者正则之类的,例如时间类型的字符被JSON.parse后就会是字符串形式,而不是时间对象。

2)会丢失对象的constructor,所有的构造函数会指向Object

3)对象有循环引用,会产生报错。

4)对象中有undefined,symbol的类型的对象,序列化后结果会把undefined丢失,NaN,Infinity序列化后结果会变成null。

2、使用**object.assign()**用于将所有可枚举属性的值从一个或者多个源对象分配到目标对象,然后然会目标对象。

const newObj = Object.assign([],oldObj);

缺点:

只对顶层对象保留了赋值,没有递归向下兼容对下面的属性进行深拷贝,所以下面的对象还是浅拷贝,没有要求的可以使用。

3、使用递归的方式,创建一个新对象,产生一个新地址,,就不会产生上面两种的问题。

function cloneObj(myObj) {
    if(typeof(myObj) != 'object') {
        return myObj;
    }
    var newObj;
    if(myObj.constructor) {
        newObj = new myObj.constructor();
    }else {
        newObj = {};
    }
    for(let i in myObj) {
        newObj[i] = cloneObj(myObj[i]);
    }
    return newObj;
}