前言
實作很常會遇到要讓物件複製出來,個別使用的狀況,在 JavaScript 物件複製分成兩種:
淺拷貝(shallow copy)
這邊先來看看淺拷貝的範例:
1 2 3 4 5 6 7 8
| var school = { name:'Taipei University', classes: { teacher: 'Alex', student:['Kevin','Clara','Rose'] } } var newSchool = Object.assign({}, school)
|
這樣就是典型的淺拷貝,接者修改 newSchool
的 name
屬性看看:
1 2 3 4 5 6 7 8 9 10
| var school = { name:'Taipei University', classes: { teacher: 'Alex', student:['Kevin','Clara','Rose'] } } var newSchool = Object.assign({}, school) newSchool.name = 'Taoyuan University' console.log(school.name , newSchool.name)
|
可以發現 newSchool
的 name
確實獨立被修改了,不過要注意的是,這種淺拷貝方法只會對物件第一層的屬性生效,在第二層之下的仍然是上篇文章介紹的傳參考特性,這邊來看看修改第二層的範例:
1 2 3 4 5 6 7 8 9 10
| var school = { name:'Taipei University', classes: { teacher: 'Alex', student:['Kevin','Clara','Rose'] }, } var newSchool = Object.assign({}, school) newSchool.classes.teacher = 'Mary' console.log(school.classes.teacher, newSchool.classes.teacher)
|
可以發現第二層以下的屬性,兩個物件仍會按照傳參考特性一同被修改。
在原生 JS 中淺拷貝方法較多,其他還有:
1 2 3 4 5 6 7 8 9 10 11 12
| var school = { name:'Taipei University', classes: { teacher: 'Alex', student:['Kevin','Clara','Rose'] }, }
var newSchool = { ...school } newSchool.classes.teacher = 'Mary' newSchool.name = 'Taoyuan University' console.log(school.name , school.classes.teacher)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var school = { name:'Taipei University', classes: { teacher: 'Alex', student:['Kevin','Clara','Rose'] }, } var newSchool = {} for(var key in school ){ newSchool[key] = school[key] } newSchool.classes.teacher = 'Mary' newSchool.name = 'Taoyuan University' console.log(school.name , school.classes.teacher)
|
不過實做中這種傳參考特性,有時反而達不到需求,這個時候就會想問了,JavaScript 中有沒有什麼方法,能複製兩個指向完全不同的物件?
而深拷貝就是能將物件記憶體指向完全分開的方法。
深拷貝(deep copy)
和淺拷貝不同,能夠做到深拷貝的功能,在原生 JavaScript 中只有一種寫法,如範例:
1 2 3 4 5 6 7 8 9 10
| var school = { name:'Taipei University', classes: { teacher: 'Alex', student:['Kevin','Clara','Rose'] }, } var newSchool = JSON.parse(JSON.stringify(school )) newSchool.classes.teacher = 'Mary' console.log( school.classes.teacher, newSchool.classes.teacher)
|
看到 JSON.stringify()
其實就會明白,這個方法是先透過 JSON.stringify()
將物件轉成字串,再使用 JSON.parse()
將字串轉成物件,由於有先轉成字串因此兩個物件的記憶體是完全分開的。
參考資料