通過(guò)引用傳遞和傳遞的值及其在 JavaScript 中的修改。
腳本對(duì)象引用及其副本
在處理 JavaScript 時(shí),您將面臨與 JavaScript 如何處理其基元變量和非基元變量以及何時(shí)用作值或用作引用相關(guān)的混淆。使用值時(shí),每種方法的工作方式都不同。
今天,我們將討論JavaScript如何定義其引用和對(duì)象,以及它將如何在不同的場(chǎng)合處理它們。
類型
讓我們從基礎(chǔ)開(kāi)始,有2種類型的JavaScript對(duì)象,即原始和非原始對(duì)象。基元類型包括字符串、數(shù)字、空、布爾型、BigInt、符號(hào)(新引入的)和未定義的。
另一方面,非基元類型是存儲(chǔ)中的引用,因?yàn)樗鼈儧](méi)有定義的存儲(chǔ)。非基元類型可以在存儲(chǔ)中變大,這就是為什么JS最好地將其視為也稱為對(duì)象的引用。每個(gè)對(duì)象都是從 G小葉對(duì)象類派生而來(lái)的。
每個(gè)對(duì)象都有一個(gè)分配的標(biāo)識(shí)符,該標(biāo)識(shí)符保存其引用的值,就像常規(guī)變量標(biāo)識(shí)符也具有其作用域和Unicode一樣。
更新基元類型
讓我們從基元類型開(kāi)始并更新它們。我們將首先創(chuàng)建一個(gè)字符串變量并將其分配給另一個(gè)變量,然后更新新變量并比較輸出。
基元類型示例
以下程序的輸出將是唯一的,并指出每個(gè)基元值將保存在另一個(gè)內(nèi)存地址中:
Output - test another test
更新非基元類型
當(dāng)我們使用非基元類型時(shí),期望是不同的。我們將執(zhí)行與上述相同的操作,但不是更新值,而是更新內(nèi)部的屬性。
非基元類型示例
在這種情況下,輸出將更新原始對(duì)象,因?yàn)樗鼈冎赶蛳嗤奈恢茫?/p>
Output - { name: 'another test' }
我們可以通過(guò)使用來(lái)克隆對(duì)象,并且值將有所不同。例如Object.assign
使用對(duì)象分配
在這種情況下,輸出將不同,結(jié)果將打印原始對(duì)象,因?yàn)樗鼈冎赶虿煌膬?nèi)存地址:
Output - { name: 'test' }
如果我們嵌套了非原始屬性呢?
我們正在嘗試的示例將屬性指向基元類型,但如果任何一個(gè)屬性是非基元的呢?
讓我們看看預(yù)期的場(chǎng)景,我們將在對(duì)象內(nèi)再創(chuàng)建一個(gè)非原始屬性,并將嘗試更新最新的對(duì)象并將其與現(xiàn)有對(duì)象進(jìn)行比較:
對(duì)嵌套對(duì)象使用對(duì)象分配
該程序的輸出將是:
Output - { name: 'test', properties: { location: 'location two' } }
現(xiàn)在,這是一件有趣的事情,屬性是原始的,因此具有不同的位置,但是是非原始的,并且與 共享相同的地址,并且在更新時(shí)也會(huì)更新嵌套對(duì)象。這是因?yàn)橹辉陧敿?jí)創(chuàng)建屬性,而不執(zhí)行嵌套克隆。namepropertiesobj.propertiesObject.assign
對(duì)于嵌套克隆,有一些方法,例如 。structuredClone(node v17), recursive methods, JSON.parse(JSON.stringify(obj))and third party library
將變量傳遞給函數(shù)
當(dāng)我們處理函數(shù)并傳遞值時(shí),有兩種方式按值傳遞變量或按引用傳遞變量。首先,讓我們了解JavaScript將如何定義將變量傳遞給函數(shù)時(shí)要執(zhí)行的操作。
按值傳遞與按引用傳遞
在JavaScript中,它從不顯式比較類型是值還是引用,但是當(dāng)我們調(diào)用具有很少參數(shù)的方法時(shí),會(huì)發(fā)生一個(gè)簡(jiǎn)單的機(jī)制。腳本將創(chuàng)建輸入的副本。
由于我們創(chuàng)建的每個(gè)函數(shù)都是 Function 類的導(dǎo)數(shù),因此每個(gè)函數(shù)都有一個(gè)稱為數(shù)組的屬性,并分發(fā)給該方法。在此處閱讀有關(guān)參數(shù)的更多信息。arguments
因?yàn)閰?shù)是非首字母類型。JavaScript 使用 rest 是作為數(shù)組傳遞的參數(shù),當(dāng)函數(shù)內(nèi)的任何變量更新時(shí),它是一個(gè)參數(shù)關(guān)鍵字進(jìn)行更新。Object.assign(arguments, [...rest])
由于我們創(chuàng)建了一個(gè)新的 Argument 實(shí)例,如果值是基元的,它將為非基元?jiǎng)?chuàng)建一個(gè)新地址,它將指向相同的實(shí)例變量。
傳遞基元類型
現(xiàn)在,我們知道函數(shù)將創(chuàng)建一個(gè)新變量,因此傳遞基元類型似乎沒(méi)有任何問(wèn)題,并且變量將保持其原始狀態(tài)。
將值傳遞給方法的基元示例
以下程序的輸出將是其原始狀態(tài),無(wú)需修改:
Output - test
傳遞非基元類型并更新其引用
當(dāng)傳遞非基元類型時(shí),它還會(huì)創(chuàng)建一個(gè)副本,并且將引用該值。但是當(dāng)更新引用時(shí),它現(xiàn)在將指向另一個(gè)變量,因?yàn)槲覀兿蛩峁┝艘粋€(gè)副本,而不是一個(gè)實(shí)際的對(duì)象。
將值傳遞給方法的非基元示例
以下程序的輸出仍將處于其原始狀態(tài),無(wú)需進(jìn)行任何修改,因?yàn)槲覀兏铝艘帽旧恚?/p>
Output - { name: 'test' }
傳遞非基元類型并更新其屬性
按照上面的示例,如果我們更新引用,那么它將指向一個(gè)新的內(nèi)存地址,但是如果我們更新屬性,那么它將更新值。
將非基元值傳遞給方法和更新屬性的示例
以下程序的輸出將不會(huì)處于其原始狀態(tài),并且 name 屬性將分配一個(gè)新值,因?yàn)橐貌粫?huì)使用相同的標(biāo)識(shí)符進(jìn)行修改和更新。
Output - { name: 'another test' }
結(jié)論
JavaScript是一種令人驚訝的語(yǔ)言,當(dāng)在深層次上使用時(shí),它的所有實(shí)現(xiàn)都有其調(diào)整。最復(fù)雜的情況是,當(dāng)我們處理一個(gè)嵌套對(duì)象時(shí),每個(gè)對(duì)象都有自己唯一的共享標(biāo)識(shí)符。因此,建議使用所需的引用,并始終創(chuàng)建具有屬性的嵌套對(duì)象以避免沖突。Object.assign