Подтвердить что ты не робот

Почему значение foo.x undefined в foo.x = foo = {n: 2}?

Этот код:

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

Не могли бы вы объяснить, что имеется в виду:

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

Я вижу, что {n:2} присваивается foo. Почему undefined назначен foo.x? Возвращает ли foo = {n: 2}; undefined?

4b9b3361

Ответ 1

Согласно спецификации, сначала оценивается левая часть выражения присваивания, хотя оператор имеет приоритет справа налево. Таким образом, выражение foo.x = foo = {n: 2}, которое совпадает с foo.x = (foo = {n: 2}), оценивается следующим образом:

  • Оцените левое выражение foo.x, чтобы получить ссылку, в которой будет присвоено значение правого выражения.

  • Оцените правое выражение, чтобы получить значение, которое будет назначено. Правая часть - другое выражение присваивания, поэтому оно оценивается одинаково:

    • Оцените foo, чтобы определить, где назначить.
    • Оцените выражение {n:2}, которое создает объект, чтобы определить значение для назначения.
    • Назначьте {n:2} в foo и верните {n:2}.

  • Назначьте значение, которое выражение с правой стороны оценило ({n:2}), на ссылку, которую foo.x разрешал на шаге 1 ( до foo, был назначен новый стоимость). То же, что и bar.x, из-за назначения bar = foo в строке раньше.

Когда это будет сделано, исходный объект, который bar по-прежнему является ссылкой, будет иметь свойство x, которое ссылается на второй созданный объект. foo также является ссылкой на этот второй объект, поэтому foo === bar.x.

Ответ 2

Поскольку доступ к ресурсу foo.x слева оценивается перед правой частью.

Позвольте сделать более понятным, что на самом деле делает ваш код, указав новые имена во временные выражения:

var foo0 = {n: 1};
var foo1 = {n: 2};
foo0.x = foo1;
foo0 = foo1;
console.log(foo0.x);

Следовательно, foo0.x есть foo1.x is undefined.

В исходном коде вы можете видеть, что bar.x is {n: 2}, подтверждающий это объяснение.

Ответ 3

В соответствии со спецификацией JavaScript левая сторона всегда оценивается сначала:

12.14.4 Семантика времени выполнения: оценка

AssignmentExpression [In, Yield]: LeftHandSideExpression [? Yield]= AssignmentExpression [? In,? Yield]

Если LeftHandSideExpression не является объектом ObjectLiteral или ArrayLiteral, тогда 1. Пусть lref является результатом оценки LeftHandSideExpression.

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-assignment-operators-runtime-semantics-evaluation

Это можно четко увидеть, если добавить еще одну ссылку на объект foo:

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

ref.x существует, потому что foo.x относится к немодифицированному значению foo.

Ответ 4

Поскольку вы переназначили foo для объекта с единственным свойством, { n: 2 }.

В JavaScript выражения вычисляются справа налево. Поэтому, когда вы пытаетесь получить доступ к foo.x, вы пытаетесь получить значение x из вновь назначенного значения foo, { n: 2 }, которое равно undefined.