一、賦值(copy)
賦值是將某一數值或物件賦給某個變數的過程,分為下面 2 部分:
基本資料型別:賦值,賦值之後兩個變數互不影響
引用資料型別:賦址,兩個變數具有相同的引用,指向同乙個物件,相互之間有影響
let a =10;
let b = a;
console.
log(a)
;//10
console.
log(b)
;//100
a =100
;console.
log(a)
;//100
console.
log(b)
;//10
對基本型別進行賦值操作,兩個變數互不影響。
let a =
;let b = a;
console.
log(a);//
console.
log(b);//
a.age =19;
console.
log(a);//
console.
log(b)
;//
對引用型別進行賦址操作,兩個變數指向同乙個物件,改變變數 a 之後會影響變數 b。
通常在開發中並不希望改變變數 a 之後會影響到變數 b,這時就需要用到淺拷貝和深拷貝。
二、淺拷貝(shallow copy)
1、什麼是淺拷貝
建立乙個新物件,這個物件有著原始物件屬性值的乙份精確拷貝。如果屬性是基本型別,拷貝的就是基本型別的值,如果屬性是引用型別,拷貝的就是記憶體位址 ,所以如果其中乙個物件改變了這個位址,就會影響到另乙個物件。簡單來說可以理解為淺拷貝只解決了第一層的問題,拷貝第一層的基本型別值,以及第一層的引用型別位址。
2.下面說說淺拷貝的幾個方法:
一.object.assign(用於將所有可列舉屬性的值從乙個或多個源物件複製到目標物件。它將返回目標物件)
object.assign方法實行的是淺拷貝,而不是深拷貝。也就是說,如果源物件某個屬性的值是物件,那麼目標物件拷貝得到的是這個物件的引用
let a =
;let b = object.
assign
(,a)
;console.
log(a)
;// ;
console.
log(b)
;// ;
a.sports.
push
("basketball"
)console.
log(a)
;// ;
console.
log(b)
;// ;
上面**改變物件 a 之後,物件 b 的基本屬性保持不變。但是當改變物件 a 中的物件 sports 時,物件 b 也發生了變化。
二.array.prototype.slice()
返回乙個新的陣列物件,這一物件是原陣列的淺拷貝。原始陣列不會被改變。
let a =
["1"
,"2",]
;let b = a.
slice(2
);console.
log(b)
;// ;b[0
].age =
"19"
console.
log(a)
;// ["1","20",];
console.
log(b)
;// ;
實際開發中我們可能經常會碰到,對乙個陣列進行拷貝,然後對拷貝的陣列進行操作,其實是會影響到原陣列的,這點我們需要記住,array.prototype.slice()是淺拷貝!
三、深拷貝(deep copy)
1、什麼是深拷貝
深拷貝會拷貝所有的屬性,並拷貝屬性指向的動態分配的記憶體。當物件和它所引用的物件一起拷貝時即發生深拷貝。深拷貝相比於淺拷貝速度較慢並且花銷較大。拷貝前後兩個物件互不影響。
2.下面說說淺拷貝的幾個方法:
一.json.parse(json.stringify())
let a =
;let b =
json
.parse
(json
.stringify
(a))
;console.
log(a)
;// ;
console.
log(b)
;// ;
a.sports.
push
("basketball"
)console.
log(a)
;// ;
console.
log(b)
;// ;
完全改變變數 a 之後對 b 沒有任何影響,這就是深拷貝。
看下對陣列深拷貝效果如何
let a =
["1"
,"2",]
;let b =
json
.parse
(json
.stringify
(a.slice(2
)));
console.
log(b)
;// ;b[0
].age =
"19"
console.
log(a)
;// ["1","20",];
console.
log(b)
;// ;
對陣列深拷貝之後,改變原陣列不會影響到拷貝之後的陣列。
但是該方法有以下幾個問題。
(1)、會忽略 undefined
(2)、會忽略 symbol
(3)、不能序列化函式
(4)、不能解決迴圈引用的物件
(5)、不能正確處理new date()
(6)、不能處理正則
let a =[}
];console.
log(a)
;// [
// }];
let b =
json
.parse
(json
.stringify
(a))
;
console.
log(b)
;//
undefined、symbol 和函式這三種情況,會直接忽略。
let obj =};
obj.b = obj.c;
obj.c.d = obj.b;
let b =
json
.parse
(json
.stringify
(obj));
console.
log(b)
;// uncaught typeerror: converting circular structure to json
// --> starting at object with constructor 'object'
// --- property 'd' closes the circle
// at json.stringify ()
迴圈引用情況下,會報錯。
let time =
newdate()
;console.
log(time)
//sat may 30 2020 16:35:38 gmt+0800 (中國標準時間)
let time1 =
json
.parse
(json
.stringify
(time));
console.
log(time1)
;
new date 情況下,轉換結果不正確。
let a =
;console.
log(a)
// let b =
json
.parse
(json
.stringify
(a))
;console.
log(b)
;// ,
// }
正則情況下,轉換結果直接是個物件。
除了上面介紹的深拷貝方法,常用的還有jquery.extend()等,有興趣的朋友可以自己去了解下!
四、總結
賦值,如果是引用型別,和原資料是指向同一物件,改變會使原資料一同改變,如果是基本型別,改變不會使原資料一同改變!淺拷貝的話,如果第一層有基本型別,改變基本型別不會影響原資料的基本型別資料,如果還有引用型別,改變引用型別會影響原資料的引用型別資料(淺拷貝只拷貝一層),深拷貝的話,不管是基本型別還是引用型別,怎麼改都不會影響原資料!
淺拷貝 深拷貝和淺賦值 深賦值
include includeusing namespace std class string else 淺拷貝 也就是系統預設的拷貝,可寫可不寫。string const string s 預設的拷貝構造 深拷貝 string const string s string s2 s1 深賦值 str...
賦值 淺拷貝 深拷貝
堆是動態分配記憶體,記憶體大小不一 棧是自動分配相對固定大小的記憶體空間,並由系統自動釋放 基本資料型別值是不可變的,比較是值的比較 基本資料型別,傳值。開闢乙個新的記憶體空間 js 基本資料型別,儲存在 棧 中,記憶體可以及時 引用型別值是可變的,比較是引用的比較,看其引用是否指向同乙個物件 引用...
深拷貝 淺拷貝 賦值
賦值 class teacher class student student s1 new student student s2 s1 s1 s2,指向的記憶體區域相同 拷貝 class teacher class student implement cloneable student s1 new...