我们在对数据进行克隆时会遇到两种数据类型,即基本数据类型和引用数据类型.
对于基本数据类型,不需要讨论深度克隆和浅度克隆的问题;而对于引用数据类型,我们需要根据需要对其进行浅克隆(简单的地址引用操作)或深克隆(不只是引用地址的赋值,而是将原本的数据克隆一份,让其不再对原本的数据产生影响).
- 浅克隆
针对数组浅克隆的数据拷贝只是简单的地址引用操作,实现起来比较简单.
直接赋值:
var arr1 = [1,2,3,4]
var arr2 = arr1;
arr1[0] = 7;
console.log(arr1); //[7, 2, 3, 4]
console.log(arr2); //[7, 2, 3, 4]
运用数组的slice方法:
var arr1 = [1,2,3,4]
var arr2 = arr1.slice()
arr1[0] = 7;
console.log(arr1); //[7, 2, 3, 4]
console.log(arr2); //[1, 2, 3, 4]
当数组元素全都是基本类型时此方法适用,但是当数组中包含对象时,此方法失效:
var arr1 = [1,{name:'Jone',age:7},3,4]
var arr2 = arr1.slice()
arr1[1].name = 'Anna';
console.log(arr1); //[1,{name:'Anna',age:7},3,4]
console.log(arr2); //[1,{name:'Anna',age:7},3,4]
- 深克隆
这里提供一种利用递归的方法实现对象的深度克隆
Object.prototype.clone = function(deep){
// 判断调用克隆这个函数的是什么类型
// 判断是否是数组
if(Array.isArray(this)){
// 判断是否深度克隆
if(deep){
var arr = [];
for(var i = 0; i < this.length; i++){
arr.push(this[i].clone(true));
}
return arr;
}else{
// 浅克隆直接截取全部复制返回
return this.slice;
}
}else if(Object.prototype.toString.call(this) === '[object Object]'){
// 判断是否是对象
var obj = {};
for(var key in this){
// 判断是否深度克隆
if(this.hasOwnProperty(key)){
if(deep){
obj[key] = this[key].clone(true)
}else{
// 浅克隆直接赋值
obj[key] = this[key];
}
}
}
return obj;
}else{
return this;
}
}
验证一下:
var obj1 = {
name:'zhangsan',
age:18,
obj:{hobby:'sleep',food:'cake'}
}
var obj2 = obj1.clone(true);
obj1['obj'].hobby = 'fishing'
console.log(obj1);
console.log(obj2);