对象克隆

108 阅读4分钟

对象克隆

1、克隆的概念

浅度克隆:原始类型为值传递,对象类型仍为引用传递。

  深度克隆:所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修改都不会反映到原对象中。

2、js中的对象

js中的数据类型分为两大类:原始类型和对象类型。

     (1)原始类型包括:数值、字符串、布尔值、null、undefined

    (2)对象类型包括: 对象即是属性的集合,当然这里又两个特殊的对象----函数(js中的一等对象)、数组(键值的有序集合)。

这两种类型在复制克隆的时候是有很大区别的。原始类型存储的是对象的实际数据,而对象类型存储的是对象的引用地址

对象的原型也是引用对象,它把原型的方法和属性放在内存当中,通过原型链的方式来指向这个内存地址。

3、浅克隆的表现

浅克隆就是将栈内存中的引用复制一份,赋给一个新的变量,本质上两个指向堆内存中的同一地址,内容也相同,其中一个变化另一个内容也会变化(根本上改变的是同一个对象)。

image-20211109114006889.png

在浅克隆中,如果原型对象的成员变量是基本类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

1、数据类型

1、基本数据类型:

字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)

// 浅对象克隆的表现// 原始数据类型
    // 1、数值类
​
     var a = 1;
​
     var b = a;
​
     a=3;
​
     console.log('a='+a);    //  3
​
     console.log("b="+b);    //  1
​
     // 2、字符串
​
      var a = '你好';
​
      var b = a;
​
      a='哈喽';
​
      console.log('a='+a);    //  哈喽
​
      console.log("b="+b);    //  你好
// 基本类型赋值,a变化并不会影响b。
    // 基本数据类型是直接存储在栈内存中的

原始类型即使我们采用普通的克隆方式仍能得到正确的结果,原因就是原始类型存储的是对象的实际数据。

2、引用类型:

对象(Object)、数组(Array)、函数(Function)。

// 引用数据类型
​
     var a = [1, 2, 3, 4]
​
      var b = a;
     console.log(b)    // [1, 2, 3, 4]
      a = [5, 6, 7, 8]
​
     console.log(b)  // [1, 2, 3, 4]

2、对象数据类型

// 对象数据类型
​
      var a = function () {
        alert(3);
      };
      var b = a;
     b=function(){alert(4);}
     console.log(a());    //  3  undefined
     console.log(b());    //  4  undefined

4、深度克隆

深克隆就是创建一个新的对象,开辟一块内存,然后将原对象中的数据全部复制过去,新对象和原对象毫无关系,互不影响。 深克隆本质上是创造一个完全一样的对象

image-20211109114028961.png

在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。

方法一: 递归
function deepClone( obj ){
    let objClone = Array.isArray(obj) ? [] : {};
    if( obj && typeof obj==="object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}    
let a=[1,2,[2, 3],4],
    b=deepClone(a);
a[2][0]=10;
console.log(a,b);
方法二: JSON.stringify 和 JSON.parse
function deepClone(obj){
    let _obj = JSON.stringify(obj),
        objClone = JSON.parse(_obj);
    return objClone
}    
let a=[0,1,[2,3],4],
    b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
方法三: jQuery中的 $.extend

$.extend( [deep ], target, object1 [, objectN ] ) deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝 target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。 object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。

let a=[0,1,[2,3],4],
    b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);