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