2017-03-25 73 views
1

說我做一個對象,將其複製(如附圖),然後廢掉它:爲什麼重新分配時不會將此對象複製爲空?

let obj = { 
 
    prop: 'one' 
 
} 
 

 
let otherObj = obj 
 

 
console.log(otherObj === obj); //true 
 

 
console.log(obj.prop); //one 
 

 
obj = null; 
 

 
console.log(otherObj.prop); //shouldn't this be Uncaught TypeError: Cannot read property 'prop' of null"?

不宜otherObj也爲空,因爲它們是同一個對象?

+1

不,你只是改變var指向的內容,而不是目標本身。如果你修改了這個對象,兩個變量都會反映出來。把第二個var作爲別名;你刪除了暱稱,而不是該人。 – dandavis

回答

1

您必須將對象和參考區分爲該對象。變量objotherObj只是持有對象的引用,該對象是指向內存的指針。 它們不是對象的副本,它們不是同一個對象。他們指向爲同一個對象。

爲了更清楚地說明這一點,我將逐行解釋。當你這樣做:

let obj = { 
    prop: 'one' 
} 

你正在創建一個新的參考,像這樣:

enter image description here

obj只是指向對象所在的內存斑點,稱爲引用。接下來,你這樣做:

let otherObj = obj 

即相當於此:

enter image description here

在這裏,您分配obj引用otherObj。他們現在都在內存中引用同一個對象,儘管它們完全相互獨立。 otherObjobj的參考文獻的shallow copy,所以它們都指的是相同的對象,但是是分開的。每鏈路:

在這種情況下新的對象B被創建,並且A的字段值被複制到B.

[...]

如果字段值是對一個對象的引用(例如,,內存地址)它複製引用,因此指的是同一對象作爲不

最後你這樣做:

obj = null 

這是這樣的:

enter image description here

obj到內存中的對象的引用基本上被切斷,現在obj p打到null,或什麼也沒有。由於objotherObj彼此獨立,所以otherObj沒有任何反應,它仍然指向內存中的對象。 objotherObj本身是獨立的引用,但引用同一個對象。當您在內存中修改對象時,它會反映在兩個引用上,但是當您通過中斷對內存位置的引用來修改引用時,另一個事件不會發生任何變化。

0

不,因爲參考在您完成新任務obj = null的確切時刻丟失,其他對象仍將包含舊的參考。

換句話說,因爲你修改的對象(例如,改變它的一些字段),都otherObjobj將會看到更新,但是當你重新分配你打破債券其中之一,每一個都會參考到記憶中的不同位置。

0

不,理解爲什麼你需要理解「參考」的概念。

在您的例子的代碼此位「創建」您的對象:

let obj = { 
    prop: 'one' 
} 

在這種情況下,「OBJ」是不是對象本身(如存儲器位置),但是對象「參照」 - 基本上它是一個指針指針。

將「obj」設置爲null之前,還將「otherObj」指定爲對SAME對象的引用。此時您有2個參考。

當您將「obj」設置爲null時,該對象仍然存在,並仍被「otherObj」引用。它將被保存在內存中,至少直到它不再被「otherObj」引用。如果您將兩個引用都設置爲null,那麼您將不再能夠訪問該對象本身,並且可能使其可以被Javscript引擎釋放。

這是一個非常重要的概念 - 如果你將一個變量傳遞給一個函數,那個參數就是對象的「引用」(除了字符串和數字之類的東西,它們本質上是不可變的)。您可以在函數外重新分配變量,參數將保持不變。

另外,在flipside上 - 雖然兩個引用指向相同的對象對成員的更改都反映了兩個引用。如果你想要兩個不同的副本,你必須做一些事情,比如「克隆」一個對象 - 而不僅僅是引用它。

理解引用對於管理Javascript中的閉包至關重要。

0

您應該區分深層副本和淺層副本。你在做什麼叫做淺拷貝。下面是可視化:

淺拷貝

enter image description here enter image description here enter image description here

深層複製

enter image description here enter image description here enter image description here

對於淺拷貝,您的兩個對象(objotherObj)都指向相同的內存位置。這就是爲什麼當你改變一個對象的值時,另一個對象也會被更新。

同時,對於深度複製,每個對象都有自己的內存位置。當你改變一個對象的值時,它不會影響另一個對象的值。

您可以從這個post瞭解更多。

-1

不,因爲變量在JavaScript中是無類型的。這意味着JavaScript引擎可以根據它所包含的信息來確定變量的類型。在Visual Basic中,一個非常類似的變量稱爲"variant"

所以,如果你說

let otherObj = obj; 

其中obj是一個對象的值,你現在有兩個變量,知道它們是對象,並具有相同的對象值(不進入對象是如何作爲參考實現)。

所以,如果你現在執行

obj = null; 

obj值超過編寫與價值null(順帶有一個數據類型爲「空」,只支持一個值:)。

很明顯,將一個新值賦給一個變量不應該改變另一個變量的值。編程語言依賴於此。

因此在obj的值已更新後,otherObj包含與之前相同的對象值:屬性爲「prop」,值爲「1」的對象。

相關問題