1.数组的浅克隆:
var arr = [1,2,3]; //引用类型
var arr1 = arr;
console.log(arr == arr1); //true,进行比较时,比较的是地址
arr1.push(6);
console.log(arr == arr1) //true
console.log(arr,arr1) //二者都输出[1,2,3,6]
结论:这个方式只是简单的复制了原数组,地址不会改变,当改变它们的任意一个数组时,它们都会发生改变;
针对以上出现的情况,有下列几种克隆的方式(以上面 arr 数组为例);
(1)使用数组的 concat() 方法:
var arr2 = arr.concat();
console.log(arr == arr2); //false,说明它们的地址不相同
console.log(arr2); //[1,2,3],只是简单的复制
arr2.push(5);
console.log(arr,arr2) //输出[1, 2, 3]和[1, 2, 3, 5],原数组没有发生改变,说明克隆成功
(2)重新创建一个空的数组,进行遍历赋值:
var arr3 = [];
for(var i = 0;i < arr.length;i ++){
arr3.push(arr[i]);
arr3[i] = arr[i]; //也可以这样写
}
console.log(arr == arr3); //false
arr3.unshift(6);
console.log(arr,arr3) //输出[1, 2, 3]和[6, 1, 2, 3],原数组没有改变,克隆成功
(3)
ES6中的 Array.from() 方法:
var arr4 = Array.from(arr);
console.log(arr == arr4) //false
arr4[2] = "ha"
console.log(arr,arr4) //输出[1, 2, 3]和[1, 2, "ha"],克隆成功
(4)ES6中的超引用(...)方式:
var arr5 = [...arr];
console.log(arr == arr5) //false
arr5.pop();
console.log(arr,arr5) //输出[1, 2, 3]和[1, 2],克隆成功
2.对象的浅克隆:
对象的同数组一样,都是引用类型,比较时也是比较地址,下面通过一个例子,列出对象的几种克隆方式:
var obj = {
a : 1,
b : "3",
}
(1)重新创建一个空对象,进行遍历赋值:
var obj1 = {};
for(var key in obj){
obj1[key] = obj[key]
}
console.log(obj == obj1); //false
obj1.c = "5";
console.log(obj,obj1) //输出{a: 1, b: "3"}和{a: 1, b: "3", c: "5"},克隆成功
(2)ES6中的超引用(...)方式(同数组):
var obj2 = {...obj}
console.log(obj == obj2) //false
obj2.b = "hello";
console.log(obj,obj2) //输出{a: 1, b: "3"}和{a: 1, b: "hello"},克隆成功
3.数组&对象的深度克隆
以上数组&对象的克隆仅仅是针对于纯数组或纯对象,当出现数组&对象中的元素也为对象或数组时,用以上方式就会克隆失败,以下列数组代码为例,列出两种深度克隆的方式;
var num = [1,2,["a","b"],{e:"3"}];
(1)最简单的方式,使用json序列化的方式:
var num1 =
JSON.parse(JSON.stringify(num)); //注意json书写格式
console.log(num == num1) //false
num1[2].push("c");
num1[3].e = 5;
console.log(num) //输出[1,2,["a","b"],{e:"3"}]
console.log(num1) //输出[1,2,["a","b","c"],{e:5}] ,克隆成功
(2)封装一个函数,克隆所有对象的方式:
function clone(obj){
var newObj;
if(typeof newObj = "object"){
if(obj === null){
newObj = null;
}else{
if(obj instanceof Array){ //判断obj的原型是否为Array,是返回true,否则返回false
newObj = []; //数组
for(var i = 0;i < obj.length;i ++){
newObj.push(clone(obj[i]));
}
}else{
newObj = {}; //对象
for(var j in obj){
newObj[j] = clone(obj[j])
}
}
}
}else{
newObj = obj;
}
return newObj;
}
//调用这个函数
var num2 = clone(num);
console.log(num == num2); //false
num2[2].shift();
num2[3].f = "hello";
console.log(num); //输出[1,2,["a","b"],{e:"3"}]
console.log(num2) //输出[1,2,["b"],{e:"3",f:"hello"}],克隆成功