帶你搞懂js的深拷貝
js深拷貝
在講正題之前我們要先了解數(shù)據(jù)存儲(chǔ)的方式
數(shù)據(jù)存儲(chǔ)方式
在講之前我們要先知道值類型和引用類型的存儲(chǔ)方式。
在JavaScript數(shù)據(jù)類型中有兩種數(shù)據(jù)類型。
值類型:字符串(String)、數(shù)字 (Number)、布爾 (Boolean)、空(Null)、未定義(Undefined)、Symbol。
存放在棧內(nèi)存中的簡(jiǎn)單數(shù)據(jù)段,數(shù)據(jù)大小確定,內(nèi)存空間大小可以分配。
引用數(shù)據(jù)類型:對(duì)象 (Object) 、數(shù)組 (Array) 、函數(shù) (Function) 。
存放在堆內(nèi)存中的對(duì)象,在棧內(nèi)存中存的是一個(gè)指針,這個(gè)指針指向堆內(nèi)存一個(gè)位置。再?gòu)亩褍?nèi)存中取得所需的數(shù)據(jù)。
存儲(chǔ)如下圖:

什么是淺/深拷貝
講完存儲(chǔ)的方式,我們來(lái)講講淺拷貝和深拷貝
拷貝也就是我們常常講的copy,ctrl+c,ctrl+v,那么我們來(lái)看看例子
當(dāng)我們對(duì)分別值類型和引用類型進(jìn)行賦值。
var a = 5
var b = a
b += 5
console.log('a=' + a,'b=' + b)
var arr=[1,2,3]
var brr=arr
brr.push(10)
console.log("arr為",arr)
console.log("brr為",brr)

現(xiàn)象:我們發(fā)現(xiàn)值類型并沒(méi)有互相受到影響,然而數(shù)組(引用類型)brr數(shù)組添加元素的時(shí)候改變了arr數(shù)組。
解釋分析:淺拷貝只會(huì)發(fā)生在引用類型身上,對(duì)于引用類型如果之進(jìn)行簡(jiǎn)單的賦值,只會(huì)賦值指向堆內(nèi)存的指針,這種稱為淺拷貝。而深拷貝就是完全拷貝一個(gè)引用類型,為不是地址指針。
淺拷貝看下面這張?jiān)韴D:

常用深拷貝實(shí)現(xiàn)
那么我們?cè)谫x值引用類型的時(shí)候肯定不能出現(xiàn)淺拷貝的現(xiàn)象,對(duì)原數(shù)據(jù)產(chǎn)生影響了。那么就要進(jìn)行深拷貝
1.通過(guò)JSON.stringify和JSON.parse
可以深拷貝的數(shù)組和對(duì)象,但是不能拷貝函數(shù),可以進(jìn)行對(duì)象或者數(shù)組的嵌套拷貝。
缺點(diǎn):無(wú)法實(shí)現(xiàn)對(duì)對(duì)象中方法的深拷貝
使用:
var brr=JSON.parse(JSON.stringify(arr))
例子:
var arr = {
name: '浪漫主義碼農(nóng)',
age: 20,
adress: ['jiangxi', 'changsha'],
friends: {
friend1: '張三',
friend2: '李四'
},
function(){
console.log("我是浪漫主義的對(duì)象")
}
}
var brr=JSON.parse(JSON.stringify(arr))
brr.name='法外狂徒張三'
brr.adress[0]='長(zhǎng)沙'
console.log("arr為", arr)
console.log("brr為", brr)

2.擴(kuò)展運(yùn)算符
利用了對(duì)象的結(jié)構(gòu)賦值特性方法。
缺點(diǎn):無(wú)對(duì)對(duì)象里面嵌套的對(duì)象進(jìn)行深拷貝,相當(dāng)于只是對(duì)一層引用對(duì)象進(jìn)行深拷貝
使用:
var brr={...arr}
例子:
var arr = {
name: '浪漫主義碼農(nóng)',
age: 20,
adress: ['jiangxi', 'changsha'],
friends: {
friend1: '張三',
friend2: '李四'
},
function(){
console.log("我是浪漫主義的對(duì)象")
}
}
var brr={...arr}
brr.name='法外狂徒張三'
brr.adress[0]='長(zhǎng)沙'
console.log("arr為", arr)
console.log("brr為", brr)

3.手寫(xiě)遞歸深拷貝函數(shù)
完美解決
函數(shù):
//使用遞歸實(shí)現(xiàn)深拷貝
function deepClone(obj) {
//判斷拷貝的obj是對(duì)象還是數(shù)組
var objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") { //obj不能為空,并且是對(duì)象或者是數(shù)組 因?yàn)閚ull也是object
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") { //obj里面屬性值不為空并且還是對(duì)象,進(jìn)行深度拷貝
objClone[key] = deepClone(obj[key]); //遞歸進(jìn)行深度的拷貝
} else {
objClone[key] = obj[key]; //直接拷貝
}
}
}
}
return objClone;
}
例子:
var arr = {
name: '浪漫主義碼農(nóng)',
age: 20,
adress: ['jiangxi', 'changsha'],
friends: {
friend1: '張三',
friend2: '李四'
},
fun: function(){
console.log("我是" + this.name + "的對(duì)象")
}
}
var brr = deepClone(arr)
brr.name = '法外狂徒張三'
brr.adress[0] = '長(zhǎng)沙'
console.log("arr為", arr)
arr.fun()
console.log("brr為", brr)
brr.fun()
//使用遞歸實(shí)現(xiàn)深拷貝
function deepClone(obj) {
//判斷拷貝的obj是對(duì)象還是數(shù)組
var objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") { //obj不能為空,并且是對(duì)象或者是數(shù)組 因?yàn)閚ull也是object
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") { //obj里面屬性值不為空并且還是對(duì)象,進(jìn)行深度拷貝
objClone[key] = deepClone(obj[key]); //遞歸進(jìn)行深度的拷貝
} else {
objClone[key] = obj[key]; //直接拷貝
}
}
}
}
return objClone;
}

總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
js關(guān)于getImageData跨域問(wèn)題的解決方法
這篇文章主要為大家詳細(xì)介紹了js關(guān)于getImageData跨域問(wèn)題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
parabola.js拋物線與加入購(gòu)物車(chē)效果的示例代碼
本篇文章主要介紹了parabola.js拋物線與加入購(gòu)物車(chē)效果的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
JavaScript實(shí)現(xiàn)焦點(diǎn)進(jìn)入文本框內(nèi)關(guān)閉輸入法的核心代碼
這篇文章給大家分享js實(shí)現(xiàn)焦點(diǎn)進(jìn)入文本框內(nèi)關(guān)閉輸入法,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-09-09
淺談js中子頁(yè)面父頁(yè)面方法 變量相互調(diào)用
下面小編就為大家?guī)?lái)一篇淺談js中子頁(yè)面父頁(yè)面方法 變量相互調(diào)用。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-08-08
JavaScript限定復(fù)選框的選擇個(gè)數(shù)示例代碼
有10個(gè)復(fù)選框,用戶最多只能勾選3個(gè),否則就灰掉所有復(fù)選框,具體實(shí)現(xiàn)思路及代碼如下,感興趣的朋友可以參考下,希望對(duì)大家有所幫助2013-08-08

