2016-06-07 16 views
7

Tôi có một câu hỏi ngu ngốc. Trong đoạn mã dưới đây, hàm doStuff xuất hiện để gán lại myArray cho một mảng trống, nhưng khi thử nó trong giao diện điều khiển, myArray vẫn là [2,3,4,5].Tham chiếu các mảng trong Javascript

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

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

Hơn nữa, một chức năng mà đổi mảng dường như làm việc tốt. Ví dụ:

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

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

Ai đó có thể giúp tôi hiểu điều gì đang xảy ra ở đây? Cảm ơn.

+1

có thể trùng lặp của [Javascript qua mảng chức năng theo giá trị, để lại mảng ban đầu không thay đổi gì] (http://stackoverflow.com/questions/14491405/javascript-passing-arrays-to- function-by-value-leave-original-array-unaltere) – ManoDestra

+1

@ManoDestra Câu hỏi đặt ra ở đây là 'tại sao nó xảy ra' và câu hỏi trong bài đó là' cách sửa chữa nó'. Hai câu hỏi khác nhau từ quan điểm của tôi. –

+0

Câu hỏi này được trả lời bởi người khác khi nó được hiểu. – ManoDestra

Trả lời

3

Mảng được chuyển bởi tham chiếu bằng JavaScript. Vì vậy, trong các hàm doStuffchangeSecondIndex của bạn, thông số arr chứa tham chiếu đến myArray.

Trong changeSecondIndex, bạn đang sử dụng tham chiếu đó để truy cập và cập nhật thuộc tính của mảng. Điều đó hoạt động tốt, như bạn có thể thấy. Nhưng trong doStuff, điều thực sự xảy ra là bạn đang đặt arr thành một mảng mới. Điều đó làm là loại bỏ thực tế rằng arr là một tham chiếu đến myArray và đặt nó vào một mảng trống mới. Đó là lý do tại sao myArray không được sửa đổi.

+1

Khi tôi hình dung doStuff làm việc, tôi thấy điều này: 'doStuff (myArray) {myArray = []}' Nhưng bạn đang nói rằng myArray trong hàm doStuff không giống với var myArray toàn cầu? – EFH

+0

'myArray' đã được * tham chiếu * trong hàm' doStuff() 'như' arr'. Nhưng những gì đã xảy ra là tài liệu tham khảo đó đã bị phá hủy. Khi bạn đã thực hiện 'arr = []', bạn đang loại bỏ giá trị cũ của 'arr' (tham chiếu) và thiết lập thành một giá trị mới (' [] '). Nghe có vẻ lạ, nhưng bạn đang đặt giá trị * của 'arr', không phải' myArray'. –

+1

Tôi cược rằng có thể gây ra một số lỗi thực sự khó hiểu. Có lẽ tôi chưa bị cắn bởi điều này (chưa?) Vì tôi cố gắng sử dụng các hàm để trả về các giá trị, thay vì thay đổi chúng tại chỗ. Một cái gì đó như thế này: thay đổi chức năngSecondIndex (arr) { arr [1] = 25; arr trả về; } myArray = changeSecondIndex (myArray); ..điều đó sẽ không cho phép vấn đề gì cả.Không phải là tôi rất tuyệt; Tôi nhận được điều này từ [ở nơi khác] (https://en.wikipedia.org/wiki/Functional_programming), tất nhiên. Tôi chỉ vui mừng khi thấy nó trả tiền theo những cách mà tôi có thể thậm chí không nhận thấy. –

-4

Bạn đã xác định var myArray toàn cục. Và sau đó bạn muốn truy cập mảng toàn cầu này và thay đổi nó trong hàm. Có nó sẽ ghi đè lên mảng toàn cầu, nhưng chỉ khi bạn cụ thể chức năng. trong hàm case của bạn doStuff().

Nếu bạn không gọi doStuff(), nó sẽ giữ giá trị inicialization toàn cầu!

+0

Anh ấy đang gọi 'doStuff (myArray);', nhưng không có gì xảy ra. –

+1

Nó không ghi đè lên mảng toàn cục, trong khi thay đổi phần tử của mảng. Đó là toàn bộ vấn đề. –

4

Mã của bạn đang tạo ra mảng trống mới, thay vào đó bạn có thể làm rỗng existing array với length = 0

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

 
doStuff(myArray); 
 
console.log(myArray)

3

mảng javacript là passed by reference, có nghĩa là chúng có thể được sửa đổi trong chức năng. Đây là lý do tại sao đoạn mã thứ hai của bạn hoạt động.

Đoạn mã đầu tiên của bạn, tuy nhiên, chỉ cần khai báo mới biến arr trong phạm vi chức năng này. Nó không ghi đè tên biến cũ, nó chỉ loại bỏ khả năng của bạn để tham chiếu đến biến toàn cầu mà bạn đã truyền vào.

Khi hàm đó thoát, biến mới arr nằm ngoài phạm vi và liên kết tên sẽ quay trở lại toàn cầu biến mà bạn đã khai báo trước đó.

Đó là lý do tại sao doStuff() không sửa đổi mảng ban đầu - vì bạn đã thực sự khai báo một mảng hoàn toàn mới vừa xảy ra để chia sẻ cùng tên trong phạm vi chức năng.

+0

* Cả hai * chức năng sẽ chứa một biến 'arr'. Đó là tham số cho hàm. 'doStuff' đặt biến đó thành giá trị. Không nơi nào nó tuyên bố một biến mới. –

+0

@RocketHazmat Không, trong đoạn đầu tiên, tên 'arr' bị ràng buộc với tham số được truyền vào. Trong đoạn thứ hai, tên' arr' được liên kết với một mảng mới '[]', bởi vì nó là một định nghĩa. –

+0

Nhưng cả hai hàm được gọi thông qua 'func (myArray)' và cả hai đều có 'arr' trong chữ ký hàm làm tham số. –

2

Đối tượng được thông qua tham khảo trong JavaScript, khi bạn gọi hàm trong ví dụ đầu tiên bạn tham số arr là một tham chiếu đến đối tượng đó được thông qua khi hàm được gọi

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] 

Trong ví dụ thứ hai bạn đang sửa đổi đối tượng được truyền, mọi thứ vẫn đang được truyền theo cùng một cách, sự khác biệt là bạn đang hành động trên đối tượng được truyền thay vì gán biến đó một giá trị mới.

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] 

Nếu bạn muốn làm một cái gì đó tương tự như những gì bạn đang cố gắng làm trong ví dụ đầu tiên có thể có một số loại đối tượng có chứa một trạng thái với các biến của bạn trong nó

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

Bạn don' t cần một hàm và đối số để thử nghiệm điều này. Trong JS []{} là các mẫu tạo đối tượng (chữ) và ngắt giới thiệu. Hãy xem ...

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 

Tất nhiên cũng áp dụng cho các đối tượng;

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

Để hiểu lý do tại sao điều này xảy ra trước tiên bạn phải nhớ rằng một Mảng trong Javascript là một đối tượng. Lý do arr = [] quý vị đang dùng không ảnh hưởng đến khai toàn cầu của bạn là dành cho những điều sau:

Lý do 1:

arr = [] không rõ ràng một mảng, nó chỉ tạo ra một đối tượng mảng mới trong bộ nhớ không có vấn đề gì .

Vì vậy, trong chức năng của bạn:

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

doStuff(myArray) 

bạn chỉ là dùng trong myArray và thực hiện một phiên bản trống mới của nó trong một phạm vi địa phương dẫn đến lý do 2.

Lý do 2:

Bất kỳ mới đối tượng/biến khai báo trong một hàm là giới hạn trong phạm vi địa phương của hàm

vậy:

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


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

arr = [] được phá hủy tại khung đóng của hàm doStuff không thể tồn tại ở bên ngoài.

Lý do 3:

function doStuff(arr){ 

arr[2] = 25; 

} 

doStuff(myArray) 

này hoạt động bởi vì bạn đang truy cập myArray trong biến arr và sửa đổi một tài sản ra khỏi đối tượng myArray, đây là hoàn toàn bình thường trong javascript.

Nói tóm lại: = hành gán, tái gán s, và tạo s ...

arr = [] là một bài tập để đối tượng myArray mới trong chức năng của bạn và là cũng bị mắc kẹt trong phạm vi chức năng của bạn.

arr[2] = 25 truy cập đối tượng myArray tạm thời và gán lại thuộc tính.

Hope this helps ..

Các vấn đề liên quan