摘要:簡單來說,就是把復(fù)制過程中的源對象都記錄下來,以及對應(yīng)的拷貝對象,碰到屬性值是之前復(fù)制過的對象的情況,的屬性值是,就把對應(yīng)的拷貝對象給它,,而不進(jìn)行遞歸深拷貝。例如的屬性值是的地址,那么拷貝過程中,的屬性值就是的地址。
基礎(chǔ)類型與引用(地址) 例子一
let a = "l am a string" let b = 6 let obj = { c: "l am an obj", d: 123 } let obj1 = obj console.log(obj1) // { c: "l am an obj", d: 123 } obj1.c = "l am an obj1" console.log(obj) // { c: "l am an obj1", d: 123 } console.log(obj1) // { c: "l am an obj1", d: 123 }
變量obj存的是地址address01,執(zhí)行let obj1 = obj后,變量obj1存的還是address01。就好像主臥室(obj),或大房間(obj1),都指的是房間號為address01的房間。所以,你說“換掉大房間的床”,obj1.c = "l am an obj1",等同于“換掉主臥室的床”,因為都是“換掉房間號為address01的房間里的床”。
例子二let a = "l am a string" let b = 6 let obj = { c: "l am an obj", d: 123 } let obj1 = {} obj1.c = obj.c obj1.d = obj.d console.log(obj1) // { c: "l am an obj", d: 123 } obj1.c = "l am an obj1" console.log(obj) // { c: "l am an obj", d: 123 } console.log(obj1) // { c: "l am an obj1", d: 123 }
變量obj存的是地址address01,執(zhí)行let obj1 = {}后,變量obj1得到了一個新的地址address02?,F(xiàn)在不僅有房間號為address01的主臥室(obj),還有房間號為address02的次臥(obj1),在那里你可以布置你自己的新房間。你可以先說“要一張和主臥一樣的床”,obj1.c = obj.c,再說“還要一臺和主臥一樣的燈”,obj1.d = obj.d,最后你又覺得床不舒服,“換了張床”,obj1.c = "l am an obj1",但這些都不會影響主臥的床obj.c。
例子三let a = "l am a string" let b = 6 let obj = { c: "l am an obj", d: 123, e: [1, 3, 5] } let obj1 = {} obj1.c = obj.c obj1.d = obj.d obj1.e = obj.e console.log(obj1) // { c: "l am an obj", d: 123, e: [ 1, 3, 5 ] } obj1.c = "l am an obj1" obj1.e[0] = 2 console.log(obj) // { c: "l am an obj", d: 123, e: [ 2, 3, 5 ] } console.log(obj1) // { c: "l am an obj1", d: 123, e: [ 2, 3, 5 ] }
主臥里面還可以有衛(wèi)生間obj.e的呢,obj.e存的也是地址adress03,只要是對象或數(shù)組都存的是地址。這時obj1.e = obj.e,存的就是主臥的衛(wèi)生間的房間號address03。目前只有一個衛(wèi)生間,你知道衛(wèi)生間的地址adress03,保存在obj1.e中,然后你就知道如何“把衛(wèi)生間的熱水器換掉”,obj1.e[0] = 2。
例子四let a = "l am a string" let b = 6 let obj = { c: "l am an obj", d: 123, e: [1, 3, 5] } let obj1 = {} obj1.c = obj.c obj1.d = obj.d obj1.e = obj.e console.log(obj1) // { c: "l am an obj", d: 123, e: [ 1, 3, 5 ] } obj1.c = "l am an obj1" obj1.e = "l am not an arr" console.log(obj) // { c: "l am an obj", d: 123, e: [ 1, 3, 5 ] } console.log(obj1) // { c: "l am an obj1", d: 123, e: "l am not an arr" }
后來你覺得知道主臥的衛(wèi)生間的地址adress03有什么用,有那閑工夫還不如用來放個柜子,故obj1.e = "l am not an arr",這樣做以后,沒有了衛(wèi)生間的地址,你就不能在主臥的衛(wèi)生間里搗亂了。
例子五let a = "l am a string" let b = 6 let obj = { c: "l am an obj", d: 123, e: [1, 3, 5] } let obj1 = {} obj1.c = obj.c obj1.d = obj.d obj1.e = [] for (let i = 0; i < obj.e.length; i++) { obj1.e[i] = obj.e[i] } console.log(obj1) // { c: "l am an obj", d: 123, e: [ 1, 3, 5 ] } obj1.c = "l am an obj1" obj1.e[0] = 2 console.log(obj) // { c: "l am an obj", d: 123, e: [ 1, 3, 5 ] } console.log(obj1) // { c: "l am an obj1", d: 123, e: [ 2, 3, 5 ] }
其實你還是想要個獨立衛(wèi)生間的,obj1.e = [],這樣你得到了房間號為adress04的房間,然后你按照主臥衛(wèi)生間的樣子來改造這個房間for (let i = 0; i < obj.e.length; i++) { obj1.e[i] = obj.e[i] }。這時候有兩個獨立的衛(wèi)生間了,房間號分別是adress04和adress03,盡管布局裝飾一樣,但還是兩個房間,賓館里的房間還都一樣呢,但它們有不同的房間號,實際上是相互獨立的房間。你換adress04房間的熱水器,obj1.e[0] = 2,并不會影響房間adress03房間。
抽象例子五的復(fù)制過程即深拷貝
let a = "l am a string" let b = 6 let obj = { c: "l am an obj", d: 123, e: [1, 3, 5] } function deepCopy(val) { if (!val || typeof val !== "object") { return val } let copy = Array.isArray(val) ? [] : {} for (key in val) { if (val.hasOwnProperty(key)) { if (val[key] && typeof val[key] === "object") { copy[key] = deepCopy(val[key]) } else { copy[key] = val[key] } } } return copy } let obj1 = deepCopy(obj) obj1.c = "l am an obj1" obj1.e[0] = 2 console.log(obj) // { c: "l am an obj", d: 123, e: [ 1, 3, 5 ] } console.log(obj1) // { c: "l am an obj1", d: 123, e: [ 2, 3, 5 ] }例子六
let a = "l am a string" let b = 6 let obj = { c: "l am an obj", d: 123, e: {} } obj.e.parent = obj let keyValArr = [] let copyArr = [] function deepCopy(val) { if (!val || typeof val !== "object") { return val } let copy = Array.isArray(val) ? [] : {} let index = keyValArr.indexOf(val) if (index === -1) { keyValArr.push(val) copyArr.push(copy) } else { return copyArr[index] } for (key in val) { if (val.hasOwnProperty(key)) { if (val[key] && typeof val[key] === "object") { copy[key] = deepCopy(val[key]) } else { copy[key] = val[key] } } } return copy } let obj1 = deepCopy(obj) obj1.e.parent.c = "l am an obj1" console.log(obj) // { c: "l am an obj", d: 123, e: { parent: [Circular] } } console.log(obj1) // { c: "l am an obj1", d: 123, e: { parent: [Circular] } }
總有人想尋根問祖,obj.e.parent = obj,如此形成了環(huán),之前的代碼就要重新調(diào)整。簡單來說,就是把復(fù)制過程中的源對象[obj, obj.e]都記錄下來,以及對應(yīng)的拷貝對象[copy, copy.e],碰到屬性值是之前復(fù)制過的對象的情況,obj.e.parent的屬性值是obj,就把對應(yīng)的拷貝對象給它,copy.e.parent = copy,而不進(jìn)行遞歸深拷貝。
從地址的角度來說,復(fù)制過程中,把地址都記錄下來,用valArr記錄源對象的地址[address01, address03],用copyArr記錄拷貝對象的地址[address02, address04],當(dāng)碰到需要拷貝的是之前記錄過源對象的地址時,就把對應(yīng)的拷貝對象的地址返回。例如obj.e.parent的屬性值是obj的地址,那么拷貝過程中,obj1.e.parent的屬性值就是obj1的地址。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/89462.html
摘要:原文地址基礎(chǔ)心法深淺拷貝歡迎。上面的代碼是最簡單的利用賦值操作符實現(xiàn)了一個淺拷貝,可以很清楚的看到,隨著和改變,和也隨著發(fā)生了變化。展開運算符結(jié)論實現(xiàn)的是對象第一層的深拷貝。 原文地址:JavaScript基礎(chǔ)心法——深淺拷貝 歡迎star。 如果有錯誤的地方歡迎指正。 淺拷貝和深拷貝都是對于JS中的引用類型而言的,淺拷貝就只是復(fù)制對象的引用,如果拷貝后的對象發(fā)生變化,原對象也會發(fā)生...
摘要:所以,深拷貝是對對象以及對象的所有子對象進(jìn)行拷貝實現(xiàn)方式就是遞歸調(diào)用淺拷貝對于深拷貝的對象,改變源對象不會對得到的對象有影響。 上一篇 JavaScript中的繼承 前言 文章開始之前,讓我們先思考一下這幾個問題: 為什么會有淺拷貝與深拷貝 什么是淺拷貝與深拷貝 如何實現(xiàn)淺拷貝與深拷貝 好了,問題出來了,那么下面就讓我們帶著這幾個問題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯誤之處...
摘要:所以,深拷貝是對對象以及對象的所有子對象進(jìn)行拷貝實現(xiàn)方式就是遞歸調(diào)用淺拷貝對于深拷貝的對象,改變源對象不會對得到的對象有影響。 為什么會有淺拷貝與深拷貝什么是淺拷貝與深拷貝如何實現(xiàn)淺拷貝與深拷貝好了,問題出來了,那么下面就讓我們帶著這幾個問題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯誤之處,還請看到的小伙伴多多指教,先行謝過 以下↓ 數(shù)據(jù)類型在開始了解 淺拷貝 與 深拷貝 之前,讓我們先...
摘要:引用和值拷貝微信公眾號開發(fā)企業(yè)級產(chǎn)品全棧開發(fā)速成周末班首期班號正式開班,歡迎搶座作者黎躍春追時間的人簡介是推出的一個天挑戰(zhàn)。深拷貝與淺拷貝對比創(chuàng)建對象黎躍春淺拷貝深拷貝將對象轉(zhuǎn)換成字符串,打印時效果清晰。 Day14 - JavaScript 引用和值拷貝 (Node+Vue+微信公眾號開發(fā))企業(yè)級產(chǎn)品全棧開發(fā)速成周末班首期班(10.28號正式開班,歡迎搶座) 作者:?黎躍春-追時間的...
摘要:棧內(nèi)存與堆內(nèi)存淺拷貝與深拷貝,可以說是前端程序員的內(nèi)功,要知其然,知其所以然。棧內(nèi)存與堆內(nèi)存中的變量分為基本類型和引用類型。 showImg(https://segmentfault.com/img/bVbuvnj?w=900&h=250); 前言 想寫好前端,先練好內(nèi)功。 棧內(nèi)存與堆內(nèi)存 、淺拷貝與深拷貝,可以說是前端程序員的內(nèi)功,要知其然,知其所以然。 筆者寫的 JavaScrip...
摘要:在中可以通過添加一個參數(shù)來實現(xiàn)遞歸,調(diào)用就可以實現(xiàn)一個深拷貝。利用序列化實現(xiàn)一個深拷貝 在JavaScript中,對于Object和Array這類引用類型值,當(dāng)從一個變量向另一個變量復(fù)制引用類型值時,這個值的副本其實是一個指針,兩個變量指向同一個堆對象,改變其中一個變量,另一個也會受到影響。 這種拷貝分為兩種情況:拷貝引用和拷貝實例,也就是我們說的淺拷貝和深拷貝 淺拷貝(shallow...
閱讀 3084·2021-11-16 11:42
閱讀 3815·2021-09-08 09:36
閱讀 1004·2019-08-30 12:52
閱讀 2552·2019-08-29 14:12
閱讀 844·2019-08-29 13:53
閱讀 3687·2019-08-29 12:16
閱讀 697·2019-08-29 12:12
閱讀 2532·2019-08-29 11:16