(Day12) 物件,浅拷贝/深拷贝

前言

实作很常会遇到要让物件复制出来,个别使用的状况,在 JavaScript 物件复制分成两种:

  • 浅拷贝
  • 深拷贝

浅拷贝(shallow copy)

这边先来看看浅拷贝的范例:

var school = {
	name:'Taipei University',  
	classes: { 
		teacher: 'Alex',
		student:['Kevin','Clara','Rose']
        }
}
var newSchool = Object.assign({}, school)

这样就是典型的浅拷贝,接者修改 newSchoolname 属性看看:

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'

可以发现 newSchoolname 确实独立被修改了,不过要注意的是,这种浅拷贝方法只会对物件第一层的属性生效,在第二层之下的仍然是上篇文章介绍的传参考特性,这边来看看修改第二层的范例:

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
  • for ... in 方法
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 中有没有什麽方法,能复制两个指向完全不同的物件?

而深拷贝就是能将物件记忆体指向完全分开的方法。

深拷贝(deep copy)

和浅拷贝不同,能够做到深拷贝的功能,在原生 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() 将字串转成物件,由於有先转成字串因此两个物件的记忆体是完全分开的。

参考资料

  • JavaScript 核心篇 (六角学院)

<<:  [Angular] Day12. Template variables

>>:  Day12:合并排序(Merge Sort)

D25 第十二周 (回忆篇)

SQL 再深入 这周进度还停留在第十一周作业,内容算是留言版的进阶版,原本的 SQL 增加了一个 J...

Day21-部署篇(三)Laravel 专案部署与 MySQL、Nginx 设定

大家好~ 继续昨天的主题, 今天要来把 Laravel 部署上 Server, 顺便设定一下 MyS...

入门魔法 - 变数宣告 let、const、var

前情提要 「我想确认一下,入门魔法都是加 100 魔力总量吗?」 艾草:「对唷!之後有中阶魔法加比较...

Day 11 - BOM (Browser Object Model)

BOM (Browser Object Model) 浏览器物件模型 JavaScript 与浏览器...