JS中數據類型
- 基本數據類型: undefined、null、Boolean、Number、String和Symbol(ES6)
- 引用數據類型: Object(Array, Date, RegExp, Function)
深淺拷貝
深淺拷貝只是針對引用類型的,因爲引用類型是存放在堆內存中,在棧地址有一個或者多個地址來指向推內存的某一數據
淺拷貝:
被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。
淺拷貝僅僅複製所考慮的對象,而不復制它所引用的對象,如果你修改了“副本”的值,那麼原來的對象也會被修改
注意:淺拷貝只進行一層拷貝
深拷貝:
深拷貝是一個整個獨立的對象拷貝,深拷貝會拷貝所有的屬性,並拷貝屬性指向的動態分配的內存。當對象和它所引用的對象一起拷貝時即發生深拷貝。深拷貝相比於淺拷貝速度較慢並且花銷較大。
深拷貝把要複製的對象所引用的對象都複製了一遍。如果你修改了“副本”的值,那麼原來的對象不會被修改,兩者是相互獨立的。
注意:深拷貝無限層拷貝
用例子看深淺拷貝
賦值實現淺拷貝
let arr = [22, 44, 66, 88];
let co = arr;
co[0] = 11;
console.log(arr, co);
結果如圖:
我們本來想把 arr 賦值給 co ,當我們修改co數組中第一個元素時,卻發現了原始數組arr發生了改變
很顯然,這就是一個淺拷貝的例子
原理:
對於引用類型,賦值操作符只是把存放在棧內容中的指針賦值給另外一個變量。
所以在賦值完成後,在棧內存就有兩個指針指向堆內存同一個數據。
也就可以說兩個變量在共用着同一個數據,這就是淺拷貝。
JSON實現深拷貝
let arr = [22, 44, 66, 88];
let jso = JSON.parse(JSON.stringify(arr));
jso[0] = 11;
console.log(arr, jso);
結果如圖:
對比之前賦值的結果,我們發現原來的數組arr並沒有被改變,可以說兩者是相互獨立的
很顯然,這就是一個深拷貝的例子
原理:
JSON.parse() 方法用於將一個 JSON 字符串轉換爲對象。
JSON.stringify() 方法用於將 JavaScript 值(通常爲對象或數組)轉換爲 JSON 字符串。
在JSON.stringify()完成後,對象就轉爲了字符串,也就可以說實實在在的複製了一個值,不存在引用之說。
再利用JSON.parse()轉爲對象,這樣達到深拷貝的目的
JSON實現深拷貝的缺陷:
來看下面例子:
let obj = {
nul: null,
und: undefined,
sym: Symbol('sym'),
str: 'str',
bol: true,
num: 45,
arr: [1, 4],
reg: /[0-9]/,
dat: new Date(),
fun: function() {},
}
console.log(JSON.parse(JSON.stringify(obj)))
結果如圖:
我們可以發現有些屬性被忽略了:
- undefined
- symbol
- function
可以看得出來JSON實現深拷貝也有不足之處
時間有限,未完待續
本篇文章接下來將會討論其他深淺拷貝的方法(如Oeject.assign(),展開運算符)