对象克隆
1、克隆的概念
浅度克隆:原始类型为值传递,对象类型仍为引用传递。
深度克隆:所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修改都不会反映到原对象中。
2、js中的对象
js中的数据类型分为两大类:原始类型和对象类型。
(1)原始类型包括:数值、字符串、布尔值、null、undefined
(2)对象类型包括: 对象即是属性的集合,当然这里又两个特殊的对象----函数(js中的一等对象)、数组(键值的有序集合)。
这两种类型在复制克隆的时候是有很大区别的。原始类型存储的是对象的实际数据,而对象类型存储的是对象的引用地址。
对象的原型也是引用对象,它把原型的方法和属性放在内存当中,通过原型链的方式来指向这个内存地址。
3、浅克隆的表现
浅克隆就是将栈内存中的引用复制一份,赋给一个新的变量,本质上两个指向堆内存中的同一地址,内容也相同,其中一个变化另一个内容也会变化(根本上改变的是同一个对象)。
在浅克隆中,如果原型对象的成员变量是基本类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。
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、深度克隆
深克隆就是创建一个新的对象,开辟一块内存,然后将原对象中的数据全部复制过去,新对象和原对象毫无关系,互不影响。 深克隆本质上是创造一个完全一样的对象
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。
方法一: 递归
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);