JS拷貝物件 淺克隆深克隆 深拷貝淺拷貝
物件簡介
js程式中都是用物件結構來描述顯示中一個事物,物件就是一組屬性和方法的集合,
面向物件三大特點: 封裝,繼承,多型,
克隆物件
淺克隆是克隆 一層,深層次的物件級別的就克隆參考地址
深克隆是克隆 多層,每一級別的資料都會克隆出來
淺克隆就是克隆了一層,除了物件是克隆的參考型別地址,其他都是 按值傳遞,有自己的記憶體空間
點擊進入查看按值傳遞
實作淺克隆方法
for in回圈
- 定義一個克隆函式用回圈一個一個把物件中的屬性賦值強行添加給新物件
- 創建一個物件,物件的屬性有:字串,物件,陣列
- 呼叫克隆函式,把剛剛創建的物件放進去
- 分別輸出得到物件的三個屬性值
- 更改克隆生成的物件中的a,b,c
- 看看原來的物件是否變化
//------------------1------------------
function clone(initalObj) {
var obj = {};
for ( var i in initalObj) {
obj[i] = initalObj[i];
}
return obj;
}
//------------------2------------------
var obj = {
a: "hello",
b:{
a: "world",
b: 21
},
c:["Bob", "Tom", "Jenny"]
};
//------------------3------------------
var cloneObj = clone(obj);
//------------------4------------------
console.log(cloneObj.a);
console.log(cloneObj.b);
console.log(cloneObj.c);
//------------------5------------------
cloneObj.a = "changed";
cloneObj.b.a = "changed";
cloneObj.b.b = 25;
cloneObj.c[3] = "Lilei";
//------------------6------------------
console.log(obj.a); //hello
console.log(obj.b); //{a:"changed",b:25}
console.log(obj.c); //['Bob','Tom','Jenny','Lilei']
通過以上代碼可以看出來,obj.b 屬性的屬性值被 修改 cloneObj.b 值的時候修改 c 和 b 是同樣的結果
事實上就是for in回圈 克隆參考型別的時候,復制的都是參考地址
ES6中的Object.assign方法
Object.assign(target, ...sources)
//引數:
// target:目標物件
// sources:任意多個源物件
//回傳值:
// 目標物件會被回傳
Object.assign() 方法用于將所有可列舉屬性的值從一個或多個源物件復制到目標物件,它將回傳目標物件,
但是 Object.assign() 進行的是淺克隆,克隆的是物件的屬性的參考,而不是物件本身,
var obj = {
a: "LiLei",
b: {
a: "LiXiaolei",
b: 21,
},
};
var cloneObj = Object.assign({}, obj);
cloneObj.a = "changed";
cloneObj.b.a = "changed";
console.log(obj.a); //LiLei
console.log(obj.b.a); // "changed"
var obj2 = { a: 1, b: 2, c: 3 };
var cloneObj2 = Object.assign({}, obj2);
cloneObj2.b = 10;
console.log(obj2);
// { a: 1, b: 2, c: 3 }
console.log(cloneObj2);
// { a: 1, b: 10, c: 3 }
可以看到修改cloneObj2.b,原來obj2沒有發生變化
實作深克隆方法
遞回拷貝
定義函式在函式執行前判斷型別:
是否為null、是就直接回傳null;
是否為陣列,是陣列利用slice方法放到一個新陣列回傳;
在遍歷的時候判斷是否為參考型別,如果原物件中當前值是原始型別就可以直接賦值,否則當前屬性不是原始型別的值,再次呼叫clone函式,繼續復制當前屬性值
var lilei={
sname:'lilei',
sage:11,
score:null,
firends:["jack","rose"],
address:{
prov:'北京',
city:'北京',
area:'海淀',
street:'成壽寺'
}
}
function clone(obj){
if(obj===null){
return null;
}
if({}.toString.call(obj)==="[object Array]"){
var newArr=[];
newArr=obj.slice();
return newArr;
}
var newobj={};
//遍歷物件中的每個屬性
for(var key in obj){
//如果原物件中當前值是原始型別就可以直接賦值
if(typeof obj[key]!=="object"){
//在新物件中添加和原物件中同名的屬性
newobj[key]=obj[key];
//因為原始型別復制就是復制副本
}else{
//否則當前屬性不是原始型別的值,再次呼叫clone函式,繼續復制當前屬性值
newobj[key]=clone(obj[key])
}
}
return newobj;
}
var lilei2=clone(lilei);
JSON.stringify()方法
用JSON.stringify把物件轉成字串,再用JSON.parse把字串轉成新的物件
var obj1 = { LiLei: { age: 21 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.LiLei.age = 25;
console.log(obj1);
// { LiLei: { age: 21 } }
console.log(obj2);
// { LiLei: { age: 25 } }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
// false
這種方法在進行深克隆后不管原物件的建構式是什么,現在的都會變成Object,所以不能對原型鏈上的屬性和方法進行克隆,
這種方法能正確處理的物件只有 Number, String, Boolean, Array, 扁平物件,即那些能夠被 json 直接表示的資料結構,function沒辦法轉成JSON,如果你的物件里有函式, 函式無法被拷貝下來,
Object.create()方法
Object.create(proto[, propertiesObject]) 僅靠父物件就可以創建子物件的一個方法,
Object.create(proto[, propertiesObject])
//引數:
// proto:新創建物件的原型物件
// propertiesObject:可選,如果沒有指定為 undefined,則是要添加到新創建物件的不可列舉(默認)屬性(即其自身定義的屬性,而不是其原型鏈上的列舉屬性)物件的屬性描述符以及相應的屬性名稱,這些屬性對應Object.defineProperties()的第二個引數,
//回傳值:
// 一個新物件,帶著指定的原型物件和屬性,
如下代碼:
var obj = {
x: 1,
y: {
a: 1,
b: 0,
c: [1, 2, 3]
}
};
var obj2 = Object.create(obj);
console.log(obj2 == obj); //false
console.log(obj2);

在輸出結果中可以看到,obj2自己并沒有屬性,屬性全部都是繼承于父物件
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/59081.html
標籤:其他
