2013-02-21 14 views
18

Tôi có một đối tượng được xác định bên ngoài hàm, trong phạm vi toàn cục. Đối tượng này không được chuyển vào hàm như một đối số, nhưng hàm này sửa đổi nó và trả về đối tượng đã sửa đổi.Chức năng Javascript có trả lại đối tượng theo tham chiếu hoặc giá trị theo mặc định không?

Điều tôi muốn biết là, nếu hàm trả về một bản sao của đối tượng hoặc đối tượng toàn cục gốc?

Ngoài ra, sẽ chuyển đối tượng đó đến hàm làm đối số, tạo sự khác biệt, vì đối tượng được chuyển vào hàm bằng tham chiếu?

+0

Đối tượng không bao giờ được sao chép, chỉ khi bạn làm như vậy một cách rõ ràng. –

+6

Thay vì nói "các đối tượng được truyền vào các hàm theo tham chiếu", chính xác hơn để nói rằng tham chiếu * đối tượng được truyền theo giá trị. Xem tại đây: http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language/5314911#5314911 –

Trả lời

42

Bất cứ khi nào bạn trả lại đối tượng, bạn sẽ trả về tham chiếu đến đối tượng. Tương tự như vậy, khi bạn đang truyền một đối tượng, bạn đang truyền tham chiếu. Tuy nhiên, việc chuyển đối tượng vào làm đối số có thể khác với việc thay đổi đối tượng trong phạm vi toàn cục, như các ví dụ này hiển thị. Điều này là do tham chiếu đến đối tượng được tự nó truyền theo giá trị.

Nếu bạn đang thay đổi các thành viên của một đối tượng, sau đó cho dù bạn chuyển nó thành một đối số hay chỉ cập nhật đối tượng chung thì không có sự khác biệt. Dù bằng cách nào, bạn đang làm việc với cùng một đối tượng.

Ví dụ 1:

var object = {foo:'original'}; 

function changeObject() { 
    object.foo = 'changed'; 
    return object; 
} 

console.log(changeObject()); // outputs {foo:'changed'} 
console.log(object); // outputs {foo:'changed'} 

Ví dụ 2:

var object = {foo:'original'}; 

function changeArgument(object) { 
    object.foo = 'changed'; 
    return object; 
} 

console.log(changeArgument(object)); // outputs {foo:'changed'} 
console.log(object); // outputs {foo:'changed'} 

Mặt khác, nếu bạn đang ghi đè lên các đối tượng với một đối tượng mới, sự thay đổi sẽ không tồn tại nếu bạn làm nó vào đối số, nhưng sẽ tồn tại nếu bạn làm điều đó với đối tượng chung. Đó là bởi vì đối số chuyển tham chiếu đến đối tượng theo giá trị.Một khi bạn thay thế giá trị này với một tham chiếu đến một đối tượng mới, bạn không nói về cùng một đối tượng nữa.

Ví dụ 3:

var object = {foo:'original'}; 

function replaceObject() { 
    object = {foo:'changed'}; 
    return object; 
} 

console.log(replaceObject()); // outputs {foo:'changed'} 
console.log(object); // outputs {foo:'changed'} 

Ví dụ 4:

var object = {foo:'original'}; 

function replaceArgument(object) { 
    object = {foo:'changed'}; 
    return object; 
} 

console.log(replaceArgument(object)); // outputs {foo:'changed'} 
console.log(object); // outputs {foo:'original'} 
+0

Tất nhiên nếu bạn muốn 'replaceArgument (object)' có kết quả cuối cùng giống như 'replaceObject', bạn chỉ có thể làm' object = replaceArgument (object) ' –

+6

Đây là một câu trả lời tuyệt vời. – rgthree

1

Điều tôi muốn biết là, nếu hàm trả về một bản sao của đối tượng hoặc đối tượng toàn cục gốc?

Có hiệu quả, bạn chỉ bao giờ đối phó với các tham chiếu đến các đối tượng trong JavaScript. Thậm chí var foo = {} chỉ gán một tham chiếu đến một đối tượng mới cho foo.

1

Nếu đối tượng nằm ngoài chức năng, bạn không cần phải 'trả lại' nó. Nếu bạn sửa đổi đối tượng trong hàm, nó sẽ tự cập nhật đối tượng. Sau đó, bạn có thể tham khảo đối tượng mới được cập nhật trong các chức năng khác khi cần.

+1

Điều đó có ý nghĩa. Tuy nhiên, trong trường hợp của tôi, việc trả lại nó giúp cô lập đối tượng đơn lẻ đó khỏi một bộ sưu tập khổng lồ, để tôi không cần phải thực hiện tìm kiếm đối tượng đó nữa. –

+0

Hmm. Không chắc tôi hiểu tình hình của bạn sau đó. Bạn có thể đăng một ví dụ mã không? – LoneWolfPR

1

Từ câu hỏi của bạn đây là cách tôi nghĩ rằng mã vẻ của bạn (nhiều hơn hoặc ít hơn):

var o = {}; 

function f() { 
    o.prop = true; 
    return o; 
} 
  1. Trong trường hợp này biến toàn cầu tài liệu tham khảo o một đối tượng.
  2. Khi bạn sửa đổi o, bạn đang sửa đổi bất kỳ tham chiếu o nào. Do đó nó sửa đổi đối tượng gốc.
  3. Khi bạn trả lại o bạn đang trả lại tham chiếu đến đối tượng gốc.

Chuyển đối tượng đến hàm kết quả trong tham chiếu đến đối tượng ban đầu đang được chuyển. Do đó mọi sửa đổi sẽ ảnh hưởng đến đối tượng gốc. Ví dụ:

var o = {}; 

f(o); 

console.log(o.prop); // true 

function f(o) { 
    o.prop = true; 
} 
0

thể bị trễ bình luận, nhưng đây là thách thức điển hình trong bất kỳ ngôn ngữ. Các đối tượng được tạo trên heap và được chuyển xung quanh bởi tham chiếu trái ngược với nguyên thủy (theo giá trị). Tôi nghĩ rằng gốc của câu hỏi được chia sẻ cá thể so với duy nhất để tránh các tác động không mong muốn. Ví dụ: chúng tôi gọi một hàm để lấy mẫu (đối tượng) để người dùng mới thêm vào bộ sưu tập hoặc muốn xóa biểu mẫu khi hủy sự kiện từ các mô-đun khác nhau để bắt đầu lại. Nó dễ hiểu và dễ dàng để overlook..test trường hợp thường không bao gồm tất cả các hoán vị sử dụng

Các tỉnh táo danh sách kiểm tra: Ở đây, ví dụ chia sẻ:

var bigo = { 

    usr: {name: 'steven'}, 
    bigi: function() { 
     return this.usr; 
    } 
}; 
var outA = bigo.bigi(); 

var outB = bigo.bigi(); 

print(outA.name); 

print(outB.name); 

outA.name = 'ilan'; // change value 

print(outA.name); 

print(outB.name); 

trên sản phẩm:

steven 

steven 

ilan 

ilan 

không được chia sẻ:

var bigo = { 

    bigi: function() { 
     var user = {name: 'steven'}; 
     return user; 
    } 
}; 

var outA = bigo.bigi(); 

var outB = bigo.bigi(); 


print(outA.name); 

print(outB.name); 

outA.name = 'ilan'; // change value 

print(outA.name); 

print(outB.name); 

o utput:

steven 

steven 

ilan 

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