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.bar
là undefined
thay vì foo
?
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.bar
là undefined
thay vì foo
?
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à
đánh giá foo.bar
. Điều này trả về một tham chiếu {base: Object {n:1}, property:bar}
.
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}
đặ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>")
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?
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
và 'foo2.bar === foo1; // true' –
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.
đối tượng gốc 'foo' có nó, không phải cái mới. –
Nếu bạn đã làm 'foo.bar = foo = {bar: 2}' thì sao? Điều đó hoạt động. – Luminous
@ Không có nó; 'foo.bar === 2', không phải' {n: 1} '(' foo') – Mathletics