2015-08-07 20 views
6

Xem xét các báo cáo sau:Chained phân công và tham chiếu vòng tròn trong JavaScript

var foo = {n: 1}; 
foo.bar = foo = {n: 2}; 

Bạn có thể giải thích tại sao foo.barundefined thay vì foo?

+0

đối tượng gốc 'foo' có nó, không phải cái mới. –

+0

Nếu bạn đã làm 'foo.bar = foo = {bar: 2}' thì sao? Điều đó hoạt động. – Luminous

+1

@ Không có nó; 'foo.bar === 2', không phải' {n: 1} '(' foo') – Mathletics

Trả lời

12

Khi thực thi toán tử gán, JS đánh giá phần bên trái trước tiên. Vì vậy, đây

foo.bar = foo = {n: 2}; 

được hiểu như là

  1. đánh giá foo.bar. Điều này trả về một tham chiếu {base: Object {n:1}, property:bar}.

  2. sau đó đánh giá sự phân thứ hai:

    2.1 eval foo. Điều này trả về một tham chiếu {base:<scope>, property:foo}

    2.2. eval {n:2}. Điều này tạo ra một đối tượng mới.

    2.3 giá trị thỏa: <scope>.foo = {n:2}

    2,4 trở {n:2}

  3. đặt giá trị cho các tham chiếu đầu tiên: {n:1}.bar = {n:2}. Này chạy tốt, nhưng đối tượng cũ {n:1} không truy cập được nữa, vì <scope>.foo đã đề cập đến đối tượng mới

chi tiết: http://ecma-international.org/ecma-262/5.1/#sec-11.13.1

Nếu bạn tạo một bản sao của foo trước, bạn sẽ thấy rằng tận cùng bên trái = thực sự làm thay đổi đối tượng cũ:

var foo = {n:1}; 
 
var oldFoo = foo; 
 

 
foo.bar = foo = {n: 2}; 
 

 
document.write(JSON.stringify(foo) + "<br>") 
 
document.write(JSON.stringify(oldFoo) + "<br>")

0

Bạn đã thay đổi đối tượng mà foo đề cập. Không có bar trong {n: 2}. Những gì bạn đã mong đợi?

2

Do đó, vào thời điểm gán cho foo.bar xảy ra, tham chiếu được "điền" cho foo. làm cho nó trở thành vật thể ban đầu.

Hãy mở rộng mã của bạn một chút để làm cho nó rõ ràng hơn.

var foo1, foo2; 
foo1 = foo2 = {n:1}; 
foo1 === foo2; // true 
foo1.bar = foo1 = {n:2} 
foo1.bar === foo2; // false 
foo1 === foo2; // false 
+0

và 'foo2.bar === foo1; // true' –

1

Có hai đối tượng chơi tại đây. Một sẽ có một tài sản thanh, người khác sẽ không. Để hiển thị điều này, tôi sẽ lưu trữ đối tượng gốc trong một biến khác để so sánh.

var foo = {n: 1}; 
var orig = foo; 
foo.bar = foo = {n: 2}; 
console.log(foo, orig); // {n:2}, {n:1, bar: {n:2}} 

Cho đến khi dòng foo.bar được thực hiện thực hiện, foo vẫn còn chứa các đối tượng gốc, do đó tài sản thanh của đối tượng gốc sẽ được thiết lập để các đối tượng mới.

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