淺拷貝:只遍歷一層,如果存在數組成員是對象,[{name:'jack'}],不會對對象里的值進行遍歷拷貝。
其實根據淺拷貝的方法不同,也有不同的效果。
1. 其中最弱的淺拷貝為直接賦值
let arr2 = arr1;
是直接將整個arr1數組的地址賦給arr2,故arr2的任意值(為什么說任意值呢?因為后面會介紹到,有些淺拷貝,可以使部分值看上去有深拷貝的效果)改變,都會影響到arr1。
2. 接下來介紹的四種淺拷貝方法就厲害一些了,它們在有些情況(原數組里的數據不包含引用類型)下也能達到深拷貝效果(沒錯只是披着狼皮的小綿羊啦,本質還是淺拷貝)。
一個數組變化,另一個數組不受影響。
原數組里的數據不包含引用類型
let arr1 = [1 , 2 , 3]; //原數組
1.使用拓展運算符
let arr2 = [...arr1];
//等價於
let arr2=[1, 2, 3];
//這也就是它不同於arr2=arr1的地方,
2.使用assign()
let arr2 = Object.assign([],arr1);
3.使用concat()
let arr2 = [].concat(arr1);
因為 concat()
返回的是一個副本,所以這個時候改變 arr1
就不會導致 arr2
改變了。
4.使用slice()
let arr2 = arr1.slice(0);
深拷貝:就是不管里面多少層,都遍歷,克隆一個與舊不相關的,修改新的不影響舊的。
原數組里的數據包含引用類型
let arr1 = [1 , 2 , 3 , {"name" : "張小二"} , {"sex" : "male"}]; //原數組
使用上述方法均不能實現全部深拷貝,非引用類型的值不會受影響,嵌套的一層引用類型的值會受影響。
解決方法:
方法一:遞歸
let cloneObj = function(obj){ let str, newobj = obj.constructor === Array ? [] : {}; if(typeof obj !== 'object'){ return; } else if(window.JSON){ str = JSON.stringify(obj), //系列化對象 newobj = JSON.parse(str); //還原 } else { for(var i in obj){ newobj[i] = typeof obj[i] === 'object' ? cloneObj(obj[i]) : obj[i]; } } return newobj; }; let arr2 = cloneObj(arr1);
方法二:通過JSON解析解決
let arr2 = JSON.parse(JSON.stringify(arr1));
注意:這種方法拷貝后的數組會丟失原數組中定義的方法和數組原型中定義的方法。