Это ожидаемое поведение.См. спецификацию :
Простое назначение (=)
Производственное AssignmentExpression: LeftHandSideExpression = AssignmentExpression оценивается следующим образом:
- Пусть lref будет результатом вычисления LeftHandSideExpression.
- Пусть rref будет результатом оценки AssignmentExpression.
- Пусть rval будет GetValue (rref).
- Создайте исключение SyntaxError, если(... неважно)
- Call PutValue (lref, rval).
- Возвращает 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);