Что выводится для foo.x - PullRequest
2 голосов
/ 13 мая 2019
var foo = {n: 1};
var bar = foo;
foo.x = foo = {n: 2};

что выводится для foo.x.Моя мысль - оценка справа налево, поэтому она равна

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

, поэтому она будет

{
    n: 1
    x: {n: 2}
}

Но это не так, она не определена?Я запутался в поисках объяснения.

1 Ответ

2 голосов
/ 13 мая 2019

Это ожидаемое поведение.См. спецификацию :

Простое назначение (=)

Производственное AssignmentExpression: LeftHandSideExpression = AssignmentExpression оценивается следующим образом:

  1. Пусть lref будет результатом вычисления LeftHandSideExpression.
  2. Пусть rref будет результатом оценки AssignmentExpression.
  3. Пусть rval будет GetValue (rref).
  4. Создайте исключение SyntaxError, если(... неважно)
  5. Call PutValue (lref, rval).
  6. Возвращает rval.

Короче говоря, когда интерпретатор видит x = <expression> или x.prop = <expression>, он сначала определяет, что назначить, то есть выражение LeftHandSideExpression.Затем, после оценки правой части (AssignmentExpression) значения, оно присваивает значение тому, что было первоначально , идентифицированным как LeftHandSideExpression.Таким образом, при

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

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

Вы можете видеть, как bar, который ссылается на тот же объект в памяти, что и оригинальный foo, мутирует:

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

console.log(bar);
...