2013-06-28 17 views
1

我在this blog上讀到關於如果一個對象或數組在函數內部被改變時,指向的內存中的值也會被改變,就像它在函數外被改變一樣。爲什麼在函數中改變的對象改變了它們在內存中的指向,但有時會創建一個新的內存對象?

var a = [1,2,3], 
    b = a; 

b[0] = 5; 
console.log(a); // [5, 2, 3] 

會導致相同

var a = [1,2,3], 
    b = a; 

var arrayFunction = function(arr){ 
    arr[0] = 10; 
}; 

var arr = arrayFunction(b); 

console.log(a, b, arr) // [10, 2, 3], [10, 2, 3], [10, 2, 3]; 

但我不明白的是,爲什麼在函數內部重新分配多陣列值不改變它之外的值:

var a = [1,2,3], 
    b = a; 

var arrayFunction = function(arr){ 
    arr = ["a", "b", "c"]; 
    return arr; 
}; 

var result = arrayFunction(b); 
console.log(result) //["a", "b", "c"] 
console.log(a, b); //[1, 2, 3], [1, 2, 3] 

爲什麼不像第一個例子那樣改變內存中指向的值?

大概就the JSBIN

+2

這應該回答你的問題:http://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value – Pevara

回答

2

請記住,在函數內,arr不是實際的數組; arr是指向數組的引用。

所以,當你說arr[0],你正在檢索數組,然後獲取或更新其中的項目。

但是當您說arr = ["a","b","c"]時,您正在創建一個新對象(在右側),然後將arr轉換爲指向新對象的引用。

+0

哦。明顯!啊。這現在非常有意義。 – 1252748

+0

非常感謝 – 1252748

3

寫出的例子這更好的工作是因爲在JavaScript對象不是真的通過引用傳遞。我已經看到它被稱爲「通過複製引用傳遞」或「通過句柄傳遞」 - 兩者都更好地描述真正發生的事情。

在這個例子中:

var b = [1, 2, 3]; 
var arrayFunction = function(arr) { 
    arr = ["a", "b", "c"]; 
}; 
arrayFunction(b); 

的對象引用本身由值來傳遞。你實際上並沒有改變b變量的值。但是,您的函數參數(arr)和b變量最初指向同一個對象 - 因此,如果您更改一個對象,則可以通過任一方式引用對象並查看更改。

當您重新指定arr指向不同的對象時,b變量仍然指向舊對象,並且不會更改。

+0

是的。絕對。太感謝了。由於某種原因,只是沒有點擊我。 – 1252748

1

在Javascript中,只有一個變量指向;所以,如果你複製的變量,你得到兩個變量指向同一個數組:

var a = [1,2,3]; 
var b = a; 

改變與a[0] = 99數組的元素會觀察到有兩個變量,因爲只有一個陣列和兩個ab指向到它。

當你寫,而不是

a = [5, 6, 7]; 

要設置a指向另一個不同的陣列。

除非明確要求,否則JavaScript不會複製數組(如使用b = a.slice())。

實際上,任何值都會發生同樣的情況(例如對象)。使用數字和字符串相同的邏輯也是有效的,但很難注意到副本和共享同一對象之間的區別,因爲數字和字符串不能更改(「不可變」)。

在其他語言如C和C++中,變量包含值而不是指針;所以當做一個賦值時,例如對象從一個變量複製到另一個變量,如果你想要一個指針,你必須明確地詢問它。

相關問題