2012-01-09 25 views
5

Các ví dụ cơ bản:Hoạt động gán của Javascript là sao chép tài liệu tham khảo?

var b = 10; 
var c = b; 
b++; 
console.log(b,c); 

>> 11 10 

c trông giống như một bản sao của b.

Nhưng trong trường hợp khác:

var x = {}; 
var y = x; 
x.abc = 10; 
console.log(x.abc, y.abc); 

>> 10 10 

Tại sao y không phải là một bản sao của x, nhưng một tài liệu tham khảo mà chỉ vào cùng một ví dụ x điểm đến?

Ngoài ra, tôi đoán b++ tạo một phiên bản khác, vì vậy, b trỏ đến phiên bản mới nhưng c trỏ đến phiên bản cũ. Tuy nhiên ...

var u = 10; 
setTimeout(function() { 
    console.log(u); 
}, 10000) 
u++; 

>> 11 

Nếu u++ tạo ra một trường hợp mới, sau đó các u bên trong hàm nặc danh phải trỏ đến cũ u, nên không?

Trả lời

9

c trông giống như một bản sao của b.

Cả hai đều là tham chiếu đến cùng một giá trị không thể thay đổi.

Tại sao y không sao chép của x nhưng một tài liệu tham khảo mà chỉ vào dụ x điểm đến?

x là một tham chiếu đến một đối tượng ở nơi đầu tiên, vì vậy y là một bản sao của nó (một bản sao của tài liệu tham khảo, không phải là một bản sao của đối tượng).

Nếu u++ tạo ra một trường hợp mới,

Nó không.

u trong chức năng ẩn danh nên trỏ đến cũ u, phải không?

u++ gán tham chiếu đến 11 đến u. Hàm ẩn danh đang xem u chứ không phải "giá trị của u tại thời điểm hàm được tạo".

+0

câu cuối cùng của bạn –

+1

@Quentin: do đó, "đối tượng" ban đầu chỉ nằm ở đâu đó trong 'đối tượng kích hoạt' hoặc 'môi trường từ vựng' được tạo bởi thực thi js (ES3/5) và không bao giờ thực sự bị xúc động bởi E Bản thân CMAscript. – jAndy

+0

"Cả hai đều là tham chiếu đến cùng một giá trị bất biến". Điều đó không mâu thuẫn với đầu ra quan sát được "11 10"? Đầu ra sẽ gợi ý rằng chúng là tham chiếu đến các giá trị khác nhau – Neptilo

8

Khi phân bổ nguyên thủy, chúng được gán theo giá trị; các kiểu tham chiếu (như đối tượng của bạn) được gán bằng cách tham chiếu (hoặc, như Jon Skeet sửa chữa cho tôi, chúng được gán một bản sao của tham chiếu).

Trong ví dụ thứ hai của bạn x và y cả hai trỏ đến cùng một đối tượng trong bộ nhớ. Đó là lý do tại sao thêm một tài sản abc một, cũng cho biết thêm nó vào khác

Bạn cũng sẽ theo dõi các hành vi tương tự đi qua x hoặc y vào một chức năng

function addABC(foo) { 
    foo.abc = 10; 
} 

var x = {}; 
var y = x; 
addABC(x); 
console.log(x.abc, y.abc); 

Chỉ cần lưu ý rằng, mặc dù x và y điểm đến cùng một đối tượng trong bộ nhớ, họ là bản sao riêng biệt của tham chiếu, vì vậy đây

var x = { a: 1 }; 
    var y = x; 
    y = {}; 
    alert(x.a); 

và điều này

var x = { a: 1 }; 
    var y = x; 
    x = {}; 
    alert(y.a); 

vẫn sẽ cảnh báo 1.

+1

Tôi không thích thuật ngữ "bằng cách tham chiếu" ở đây - vì * thực "tham chiếu chéo-tham chiếu hoặc sao chép theo tham chiếu là hơi khác. Ví dụ: giả sử bạn đã thay đổi phương thức' addABC' thành 'foo = "hello" ', điều đó sẽ không thay đổi giá trị của' x', phải không? (Phải thừa nhận rằng tôi * giả định * rằng JavaScript hoạt động giống như Java và C# ở đây, nhưng tôi nghĩ đó là một giả định hợp lý.) –

+0

@Jon - bạn nói đúng Tôi sẽ chỉnh sửa –

4

Tuyên bố này:

var y = x; 

bản sao giá trị của x như giá trị ban đầu của y. Tuy nhiên, các giá trị có liên quan là các tài liệu tham khảo đối với một đối tượng chứ không phải đối tượng. Lưu ý rằng đây là không phải giống như nói rằng bản sao bài tập "tham chiếu đến x" - nó thực sự là giá trị của x. Đặc biệt, nếu bạn thay đổi giá trị của x để tham chiếu đến một đối tượng khác, ví dụ:

x = "something else"; 

thì điều đó sẽ không thay đổi giá trị y - giá trị của nó sẽ vẫn là tham chiếu đến đối tượng gốc.

+1

Jon Skeet?!?! Trong thẻ JavaScript?!?! Chào mừng bạn, tốt thưa bạn! –

+3

@AdamRackis: Anh ấy đã nhúng ngón chân vào cái ao này trước đây –

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