一、淺拷貝數組
對於一個引用類型,若是直接將它賦值給另外一個對象,只是將引用地址賦值給新對象,修改一個對象另外一個也會被更改。 spa
例:prototype
var user = {
code:'0001',
name:'張三'
};
var user2 = user;
user2.name = '李四';
console.log(user);
console.log(user2);
結果:code
修改user2的name屬性,user的name屬性也被修改了。
當須要複製後的對象獨立於原對象,就要用深拷貝。 對象
二、深拷貝blog
深拷貝不是將原對象的引用賦值給新對象,而是新建一個對象,引用地址與原對象引用地址不一樣,再將原對象屬性拷貝到新對象中。有兩種經常使用方式實現引用類型的深拷貝,但都只適用於特定狀況。遞歸
1.Object.assign()方法。字符串
ES6提供了Object.assign()方法用於深拷貝。原型
例:string
var Jack ={ code:'0001', name:'張三', assing:function () { alert('張三簽到'); }, car:{ name:'路虎', type:'SVR' } } var Tom = Object.assign({},Jack); Tom.name = '趙四'; console.log(Jack); console.log(Tom); Tom.car.name='寶馬'; console.log(Jack); console.log(Tom);
結果:
能夠看到改變Tom.name屬性,Jack的name屬性並不會被更改,成功實現了深拷貝。
可是改變Tome.car.name,Jack.car.name依然會被更改。
這是由於Object.assign()方法實現只實現了一層屬性的深拷貝,屬性值若是是對象,該對象並不會被深拷貝。
2.Json.parse(Json.stringify(obj))方式
例:
var Alex = JSON.parse(JSON.stringify(Jack)); Alex.name='王五'; Alex.car.name='勞斯萊斯'; console.log(Jack); console.log(Alex);
結果:
該方法成功實現了嵌套屬性的深拷貝,可是原對象中的assign()方法丟失了。
這是由於JSON.stringify()方法將對象轉化爲字符串,但只會處理簡單屬性和簡單屬性數組,constructor屬性丟失了。
例:
console.log(JSON.stringify(Jack));
result:{"code":"0001","name":"張三","car":{"name":"寶馬","type":"SVR"}}
所以,除非對象只有簡單屬性,沒有constructor信息,才能使用Json.parse(Json.stringify(obj))作深拷貝。
3.自定義徹底深拷貝方法
遞歸遍歷對象全部屬性。
function deepClone(obj) { var type = Object.prototype.toString.call(obj); //經過原型對象獲取對象類型 var newObj; if(type ==='[object Array]'){ //數組 newObj =[]; if(obj.length >0){ for(var x=0;x<obj.length;x++){ newObj.push(deepClone(obj[x])); } } }else if(type==='[object Object]'){ //對象 newObj = {}; for(var x in obj) { newObj[x] = deepClone(obj[x]); } }else{ //基本類型和方法能夠直接賦值 newObj = obj; } return newObj; } var a1 = [1,{name:'cc',test:()=>{}},3]; var a2 = deepClone(a1); a2[1].name = '121'; console.log(a1); console.log(a2);
結果: