基礎(chǔ)類(lèi)型與引用類(lèi)型
五大基礎(chǔ)類(lèi)型
- Underfied
- Null
- Boolean
- Number
- String
他們是固定大小的數(shù)據(jù)秸脱,存在棧中,按值傳遞部蛇。
let a = 1
let b = a // ?b拷貝a
console.log(b) // 1
a = 2 // a值變了
console.log(b) // 1摊唇,b值沒(méi)有變
對(duì)基本類(lèi)型來(lái)說(shuō),拷貝就是復(fù)制一份同樣的值給對(duì)方涯鲁,雙方不會(huì)被影響巷查。
而引用類(lèi)型存的是對(duì)象的引用地址有序,對(duì)象的大小不確定,存在堆中岛请,普通的賦值拷貝只會(huì)復(fù)制一遍引用地址旭寿,實(shí)質(zhì)上兩者還是指向同一個(gè)對(duì)象。
let a = {x : 1}
let b = a // ?b拷貝a
console.log(b) // {x : 1}
a = {x : 2} // a值變了
console.log(b) // {x : 2}崇败,b也變了
淺拷貝與深拷貝
上面的例子是普通的賦值拷貝盅称,證明了對(duì)引用類(lèi)型來(lái)說(shuō)賦值拷貝是無(wú)效的,所以我們又想到了遍歷一遍對(duì)象里的值后室,那不就搞定了嗎缩膝?這就是我們說(shuō)的淺拷貝啦。確實(shí)岸霹,對(duì)一個(gè)只有一層屬性且屬性均為基本屬性的對(duì)象來(lái)說(shuō)疾层,遍歷了一遍之后會(huì)拷貝成功,互不影響贡避。但是一旦存在有屬性又是引用類(lèi)型的話云芦,還是會(huì)出現(xiàn)一樣的問(wèn)題。
所以深拷貝的直觀理解就是贸桶,對(duì)引用類(lèi)型中每個(gè)屬性進(jìn)行遍歷拷貝,直到遇到基本類(lèi)型為止桌肴。
深淺拷貝的方案
淺拷貝方案
- Object.assign() (兼容性不好)
- Underscore —— _.clone()
- lodash —— _.clone()
- 數(shù)組中concat和slice方法
深拷貝方案
- JSON.parse(JSON.stringify(obj))
簡(jiǎn)單粗暴又有點(diǎn)dirty皇筛,但是能滿(mǎn)足日常需求,只能處理json能理解的數(shù)據(jù)格式坠七,當(dāng)然不包括函數(shù)了水醋,性能也沒(méi)有特別好 - lodash —— _.cloneDeep()
很好地兼容了ES6的新引用類(lèi)型,而且處理了環(huán)型對(duì)象的情況 - jQuery —— $.clone() / $.extend()
源碼適合初學(xué)者學(xué)習(xí)彪置,比較好理解
假如說(shuō)到要來(lái)一個(gè)萬(wàn)能的完美的深拷貝方案拄踪,哦?不存在的拳魁。深拷貝本來(lái)就沒(méi)有一個(gè)明確的定義惶桐,如何處理DOM節(jié)點(diǎn)的拷貝,如何拷貝原型的屬性潘懊,RegExp 怎么處理姚糊,函數(shù)怎么處理。授舟。救恨。在知乎上有人這樣問(wèn)??
參考文章
結(jié)語(yǔ)
最近比較忙释树,其實(shí)最好還是和大家一起討論一下以上提及到的第三方庫(kù)優(yōu)秀的深拷貝源碼肠槽。擎淤。所以大家可以自行去學(xué)習(xí)~~