- 淺拷貝:指向同一個記憶體,原始值與新複製出來的值會連動
- 深拷貝:為切斷之間的關聯性,複製即產生一個新的記憶體存放,所以當改動複製出來的值時,原始值就不會隨著被更動
- 在js中,物件與陣列的複製皆屬於call by reference,所以如果以原始型別複製的方法,會有改寫原始值的問題
//原始型別如數值
let a = 7
let b = a
a = 8
console.log(a, b) //8, 7
- 由於原始型別複製是call by value(參考值,但創自己新的記憶體空間,指向的位置不同,所以改變a對b不會有影響)
- 但在陣列複製是call by reference的情況下:
const players = ['emma', 'wilee', 'stella', 'jenny']
const team = players
team[3] = 'julia'
console.log(players, team)
// ['emma', 'wilee', 'stella', 'julia']
// ['emma', 'wilee', 'stella', 'julia']
- team一改,players會跟著改,因為兩個物件指向同一個記憶體,基本上他們兩個是同一個東西,只是用不同名稱來稱呼同一個東西
- 陣列如何切斷連動關係,實現深拷貝
const players = ['emma', 'wilee', 'howord', 'jenny']
const team2 = [...players]
const team3 = [].concat(players)
const team4 = Array.from(players)
cosnt team5 = players.slice()
team5[3] = 'julia'
team2[3] = 'cash'
team3[3] = 'miya'
team4[3] = 'sylar'
console.log(players, team2, team3, team4, team5);
// ['emma', 'wilee', 'stella', 'jenny']
// ['emma', 'wilee', 'stella', 'cash']
// ['emma', 'wilee', 'stella', 'miya']
// ['emma', 'wilee', 'stella', 'sylar']
// ['emma', 'wilee', 'stella', 'julia']
以上四種方法都可以讓複製值存放在新的記憶體,互相不干擾
- 接下來看物件,同樣是call by reference,但深拷貝較複雜,易混淆
const person = {
name: 'julia'
age: 40
}
const driver = person
driver.gentle = 'female'
console.log(person, driver)
//可以看到原本的person跟driver連動
- 用以下這兩種作法看是否能達到深拷貝
- Object.assign()
- ... spread syntax
const person = {
name: 'julia',
age: 40
}
const driver = Object.assign({}, person)
driver.name = 'stella'
const driver2 = {...person}
driver2.name = 'amy'
console.log(person, driver, driver2)
//看起來似乎有成功但...
- 如果物件內又包一個物件(nested object),其物件仍指向同一個記憶體,所以這2種做法只達到最外層深拷貝,裡面還是一樣,
const julia = {
name: 'julia',
age: 40,
social: {
facebook: '@aaa',
instagram: '@bbb'
}
}
const dev = Object.assign({}, julia)
dev.social.instagram = '@ccc'
console.log(julia, dev);
//可以看到兩個instagram連動
//...也是得到一樣連動的結果
- JSON.parse(JSON.stringfy())
const julia = {
name: 'julia',
age: 40,
social: {
facebook: '@aaa',
instagram: '@bbb'
}
}
const dev = JSON.parse(JSON.stringfy(julia))
dev.social.instagram = '@ccc'
console.log(julia, dev);