最近在研究lodash的源碼沛硅,涉及到深 拷貝和淺拷貝的問(wèn)題眼刃,由此,搜集網(wǎng)上的資料來(lái)研究了一番摇肌。
- 共同點(diǎn): 都是在已有對(duì)象的基礎(chǔ)上拷貝一份擂红。
- 不同點(diǎn): 拷貝實(shí)例,還是拷貝引用
??首先分析兩者的共同點(diǎn)和不同點(diǎn)朦蕴。首先篮条,深拷貝和淺拷貝都是基于一些復(fù)雜的數(shù)據(jù)類型弟头,比如Object和Array吩抓,如果是基礎(chǔ)數(shù)據(jù)類型,number赴恨,boolean等疹娶,就沒(méi)什么區(qū)別了,這和引用類型和基礎(chǔ)類型所在內(nèi)存區(qū)域是堆內(nèi)存還是棧內(nèi)存有關(guān)伦连。
??淺拷貝和深拷貝斗仙得分清是拷貝引用還是拷貝實(shí)例
var obj = {
a: 1,
b: 2,
}
var obj1 = {}
function simplecopy(p, c) {
var c = c || {}
for(var key in p) {
c[key] = p[key]
}
}
simplecopy(obj, obj1)
obj1.a=3
console.log(obj.a) //1
console.log(obj1.a) //3
console.log(obj === obj1) //false
console.log(obj.a === obj1.a) //false
以上就是拷貝實(shí)例雨饺,拷貝實(shí)例就是給新的對(duì)象分配一個(gè)新的內(nèi)存空間,所以兩個(gè)變量互不干擾惑淳,值類型额港,就是基礎(chǔ)數(shù)據(jù)類型,simplecopy函數(shù)中把a(bǔ)和b兩個(gè)基礎(chǔ)數(shù)據(jù)類型歧焦,拷貝給了對(duì)象C移斩,相當(dāng)于重新分配了兩個(gè)空間,所以绢馍,obj1和obj2以及其對(duì)象都是指向兩種不同的地址向瓷。所以,===為false舰涌。
var str1 = {a: 1, b: 2 }
var str2 = str1
str2.a = 3
console.log(str1.a) // 3
console.log(str2.a) // 3
console.log(str1.a === str2.a) //true
以上就是拷貝引用猖任,因?yàn)閟tr1和str2都是對(duì)象,是引用類型瓷耙。str2=str1朱躺,實(shí)際上是將str2指向str1的應(yīng)用的地址刁赖,所以,str1和str2其指向的是同一塊內(nèi)存地址长搀,所以乾闰,改變其值,就會(huì)互相干擾盈滴。
淺拷貝
淺拷貝分成兩類.
- 一個(gè)是簡(jiǎn)單的引用拷貝涯肩,這個(gè)簡(jiǎn)單,普通的賦值就可以了巢钓。
- 還有一個(gè)是源對(duì)象拷貝實(shí)例病苗,其嵌套有子對(duì)象的話,就是拷貝引用
??如果一個(gè)對(duì)象沒(méi)有嵌套子對(duì)象的話症汹,那么就是源對(duì)象的實(shí)例拷貝硫朦,這里自己寫了一個(gè)淺拷貝方法,就是上文的simplecopy,上文的obj1和obj2都是沒(méi)有嵌套子對(duì)象的對(duì)象背镇,它的屬性就是基本數(shù)據(jù)類型咬展,所以,它的拷貝就是實(shí)例拷貝瞒斩,兩個(gè)對(duì)象指向不同的地址破婆,其屬性也指向不同的地址。但是如果胸囱,一個(gè)對(duì)象嵌套了一個(gè)子對(duì)象祷舀,對(duì)其子對(duì)象進(jìn)行賦值,那么就是烹笔,引用賦值裳扯,指向的是同一個(gè)地址。
var stu1 = {
name: "xiaoming",
info: {
score: 12,
school: "第一小學(xué)"
}
}
var stu2 = {}
simplecopy(stu1, stu2)
console.log(stu1)
console.log(stu2)
stu2.info.score = 21
console.log(stu1) // 其中的info.score值是21
console.log(stu1) // 其中的info.score值是21
testpng.png
深拷貝
至于深拷貝谤职,簡(jiǎn)單說(shuō)就是彌補(bǔ)了淺拷貝的缺憾饰豺,將被拷貝對(duì)象中的子對(duì)象遍歷一遍,賦值給空對(duì)象允蜈,然后在進(jìn)行淺拷貝冤吨,原理就是這樣,上段代碼
function deepCopy(p, c) {
var c = c || {}
for(var i in p) {
if(typeof p[i] === 'object') {
c[i] = (p[i].constructor === 'Array' ? [] : {})
deepCopy(c[i], p[i])
} else {
c[i] = p[i]
}
}
}
deepCopy(stu1, stu2)
console.log(stu1)
console.log(stu2)