2016-06-07 20 views
7

我有可能是一個愚蠢的問題。在下面的代碼中,函數doStuff似乎將myArray重新分配給一個空數組,但是當在控制檯中嘗試它時,myArray仍然是[2,3,4,5]。在Javascript中引用數組

var myArray = [2, 3, 4, 5]; 
function doStuff(arr) { 
    arr = []; 
}; 

doStuff(myArray); 
console.log(myArray)// => [2,3,4,5] 

此外,一個功能,修改陣列似乎很好地工作。例如:

function changeSecondIndex(arr){ 
     arr[2] = 25; 
} 

changeSecondIndex(myArray) 
console.log(myArray) // => [2,3,25,5] 

有人能幫我理解這裏發生了什麼嗎?謝謝。

+1

的[使用Javascript傳遞數組通過值的功能,留下原始陣列不變](可能的複製http://stackoverflow.com/questions/14491405/javascript-passing-arrays-to-函數的價值,離開原來陣列unaltere) – ManoDestra

+1

@ManoDestra這裏的問題是'爲什麼會發生',並在該職位的問題是'如何解決它'。從我的觀點來看,有兩個不同的問題。 –

+0

這個問題在被理解時由另一個回答。 – ManoDestra

回答

3

在JavaScript中,數組通過參考。因此,在您的doStuffchangeSecondIndex函數中,arr參數包含參考myArray

changeSecondIndex中,您使用該引用來訪問和更新數組的屬性。如你所見,這很好。但在doStuff中,實際發生的情況是您將arr設置爲新陣列。所做的就是刪除arrmyArray的引用,並將其設置爲新的空白數組。這就是爲什麼myArray未被修改。

+1

當我將doStuff工作可視化時,我看到:doStuff(myArray){myArray = []}' 但是您是說doStuff函數中的myArray與全局var myArray不一樣? – EFH

+0

'myArray'在'doStuff()'函數中被*引用*爲'arr'。但是,發生的事情是那個參考被摧毀了。當你做了'arr = []'時,你將刪除'arr'(一個引用)的舊值並設置一個新值('[]')。這聽起來很奇怪,但是你設置了'arr'的*值*,而不是'myArray'。 –

+1

我敢打賭,這可能會導致一些真正令人困惑的錯誤。 也許我還沒有被這個(還沒有?)咬過,因爲我嘗試使用函數來返回值,而不是原地改變它們。類似這樣的: function changeSecondIndex(arr){arr [1] = 25; return arr; } myArray = changeSecondIndex(myArray); ..根本不會允許這個問題。並不是我太棒了;當然,我從[其他地方](https://en.wikipedia.org/wiki/Functional_programming)獲得了此信息。我很高興看到它以我可能沒有注意到的方式獲得回報。 –

-4

您已經定義了全局變量myArray。然後你想訪問這個全局數組並在函數中進行更改。是的,它會覆蓋全局數組,但僅限於特定的功能。在你的case函數doStuff()中。

如果您不調用doStuff(),它將保持全局原始值!

+0

他在調用'doStuff(myArray);',但沒有任何事情發生。 –

+1

它不覆蓋全局數組,而改變數組的一個元素。這就是整個問題。 –

4

您的代碼創建新空數組,而不是可以清空現有陣列length = 0

var myArray = [2, 3, 4, 5]; 
 
function doStuff(arr) { 
 
    arr.length = 0; 
 
}; 
 

 
doStuff(myArray); 
 
console.log(myArray)

3

Javacript陣列passed by reference,這意味着它們可以函數內進行修改。這就是爲什麼你的第二個代碼片段有效。

但是,您的第一個代碼片段只是在該函數的範圍內聲明瞭一個新的變量arr。它不會覆蓋舊的變量名稱,它只會刪除您引用您傳入的全局變量的能力。

一旦該函數退出,新變量arr就會超出範圍,並且名稱綁定會回退到全局您之前聲明的變量。

這就是爲什麼doStuff()不會修改原始數組 - 因爲您實際上正在聲明一個全新的數組,它恰好在函數的作用域內共享相同的名稱。

+0

*兩個*函數都會包含一個變量'arr'。這是該函數的參數。 'doStuff'將該變量設置爲一個值。它沒有聲明一個新的變量。 –

+0

@RocketHazmat否,在第一個片段中,名稱'arr'綁定到傳入的參數。在第二個片段中,名稱'arr'綁定到一個新數組''],因爲它是一個定義。 –

+0

但是這兩個函數都是通過'func(myArray)'調用的,並且在函數簽名中都有'arr'作爲參數。 –

2

目的是通過JavaScript的引用傳遞,當你調用該函數在你的第一個例子中的參數arr是當函數被調用

var myArray = [2, 3, 4, 5]; 
function doStuff(arr) { 
    //arr is a variable that contains the first parameter used to invoke the 
    //function, if the variable is an object then it is passed by reference 
    // 
    //Here you are assigning the variable "arr" the value of a new array 
    arr = []; 
}; 

doStuff(myArray); 
console.log(myArray)// => [2,3,4,5] 

在第二個例子中傳遞的對象的引用您正在修改傳遞的對象,所有東西仍然以相同的方式傳遞,不同之處在於你在傳遞的對象上執行操作,而不是爲變量賦值一個新值。

function changeSecondIndex(arr){ 
     //Acting on index 2 of the passed array and setting the value to 25 
     arr[2] = 25; 
} 

changeSecondIndex(myArray) 
console.log(myArray) // => [2,3,25,5] 

如果你想要做類似你正在嘗試在第一個例子做可能有某種物體,它包含一個您的變量的狀態,它

var workingVars= {arr: [2, 3, 4, 5]}; 
function doStuff(env) { 
    // here you are assigning a new empty array to arr property of 
    // passed parameter 
    env.arr = []; 
}; 
doStuff(workingVars); 
console.log(workingVars.arr)// => [] 
1

你不要的東西t需要一個函數和參數來實驗。在JS []{}是對象創建模式(文字)並打破引薦。讓我們來看看...

var a = [1,2]; 
var b = [2,4]; 
var c = a; // c references a array. 
var d = b; // d references b array 
a.length = 0; // a becomes [] 
b = []; // b becomes [] 
console.log(c); // [] c still references a 
console.log(d); // [2,4] d is no more a reference to b 

當然這同樣適用於對象;

var o1 = {x:1, y:2}; 
var o2 = {x:2, y:4}; 
var p1 = o1; // p1 references o1 
var p2 = o2; // p2 references o2 
delete o1.x; 
delete o1.y; 
console.log(o1); // Object {} 
console.log(p1); // Object {} p1 still references o1 
o2 = {}; 
console.log(o2); // Object {} 
console.log(p2); // Object {x: 2, y: 4} p2 is no more a reference to o2 
0

要明白爲什麼會這樣,你必須首先記住的數組中的JavaScript是一個對象。您arr = []正在對你的全局聲明沒有影響的原因是以下:

原因1:

arr = []不清除陣列,它只是在內存中創建一個新的數組對象不管什麼 。

所以在你的函數:

function doStuff(arr) { 
    arr = []; 
}; 

doStuff(myArray) 

你只是採取在myarray的,並在局部範圍,這導致原因2使得它的一個新的空版本。

原因2:

任何新的對象/在函數聲明的變量是僅限於該函數的局部範圍

這樣:

function doStuff(arr) { 
    arr = []; 
}; 


doStuff(myArray) //logs [1,2,3,4] 

arr = []破壞在doStuff函數的結尾處處不能存在外部。

原因3:

function doStuff(arr){ 

arr[2] = 25; 

} 

doStuff(myArray) 

這工作,因爲你在編曲變量myarray的訪問和修改屬性可myarray的對象,這是在JavaScript完全正常的。

簡而言之: =操作分配重新分配 s和創建小號...

arr = []分配給新的對象myArray的你函數中,是也被困在你的功能範圍之內。

arr[2] = 25臨時訪問myArray對象,重新指定屬性

希望這有助於..