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