Унарные операторы "++" и "-" странная ситуация
Здесь тестовая ситуация для использования унарного оператора "++":
var j = 0 ;
console.log(j);
j = j++;
console.log(j);
Для этого выход:
0
0
Так как позиция оператора ++ находится в задней части операнда, поэтому его приоритет ниже приоритета назначения, я ожидал бы, что "j" сначала получит значение самого себя (i.e.0), но затем будет увеличено. Итак, почему второй вызов console.log(j)
все еще показывает "0"?
Чтобы быть ясным, я знаю, что решения:
// 1)
j++;
// 2)
++j;
// 3)
j += 1;
// 4)
j = ++j;
Но мне нужно знать, почему шаг приращения не выполняется в этом конкретном сценарии, а не как его исправить!
Ответы
Ответ 1
Это неинтуитивное (но не "странное"!) поведение при использовании post-increment.
В заявлении j = j++
выполняется следующее:
- Оцените LHS
- В этом случае ничего особенного не происходит, потому что вы просто называете переменную, но это может быть не всегда так, например.
foo() = j++
- Оценить RHS
- Возьмите текущее значение
j
(0) и запомните его как результат;
- Приращение
j
(для получения 1);
- Назначить RHS для LHS
- помните, что RHS оценивает это "запоминаемое" значение
j
(0).
В результате получается no-op.
Ключевым моментом здесь является то, что весь RHS оценивается и выполняется пост-приращение перед окончательным назначением.
http://www.ecma-international.org/ecma-262/5.1/#sec-11.3.1
http://www.ecma-international.org/ecma-262/5.1/#sec-11.13.1
Ответ 2
В соответствии с спецификациями ECMA для оператора Postfix Increment,
- Пусть lhs является результатом оценки LeftHandSideExpression.
- Выбросить исключение SyntaxError, если все условия верны:
- Тип (lhs) имеет значение Reference is true
- IsStrictReference (lhs) истинно
- Тип (GetBase (lhs)) - это запись среды.
- GetReferencedName (lhs) является либо "eval", либо "arguments"
- Пусть oldValue будет ToNumber (GetValue (lhs)).
- Пусть newValue является результатом добавления значения 1 в oldValue, используя те же правила, что и для оператора + (см. 11.6.3).
- Вызов PutValue (lhs, newValue).
- Возвращает oldValue.
Итак, ясно, что новое значение сначала устанавливается на lhs
(в данном случае j
), а старое значение возвращается в результате выражения, которое снова устанавливается в j
. Таким образом, значение не изменяется.
Ответ 3
Где ++ позволяет узнать, какое значение вы получите от него в этот момент
++j; // increment the value and then give it to me.
j++; // give me the value and then increment it.
так что вы говорили
j = j++;
установите j в значение j до того, как он будет увеличен.
Ответ 4
j = j++
означает сначала присвоить значение RHS LHS, а затем увеличить RHS на 1. С другой стороны, j = ++j
означает увеличение RHS на 1, а затем присвоение его LHS
Ответ 5
j ++ означает сначала назначить, затем увеличивать
++ j означает при первом приращении, затем назначьте
Итак,
var j = 0 ;
console.log(j);
j = ++j;
console.log(j);
0
1