Вот два ключа к пониманию разницы между условным выражением JavaScript и условным выражением Java:
Пожалуйста, прочитайте Примечания в нижней части этого раздела ECMAScript 5 аннотированных спецификаций:
http://es5.github.io/#x11.12
Теперь, пожалуйста, прочитайте раздел спецификации Java для условного выражения:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25
Вы заметите, что, как ECMAScript 5 состояний Отметим, что третий операнд в тройном оператора в Java не может быть просто любой старое выражение - это может быть только УсловнымВаражением. Однако для ECMAScript 5 третьим операндом может быть любое AssignmentExpression.
Заглядывая в спецификации Java, мы видим, что выражение является любым выражением присваивания:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.27
Но УсловноеВыражением является либо УсловноеВыражением с тройным оператором (... ...: .. ,) или просто ConditionalOrExpression (называемое LogicalOrExpression в ES5) (см. одну из первых двух ссылок выше для этой информации). "Цепочка" из того, что ConditionalOrExpression может быть начинается здесь в Java:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.24
А вот в ECMAScript 5:
http://es5.github.io/#x11.11
После "цепочки" типов выражений назад в Спецификация ECMAScript 5 (потому что ее легче отслеживать, чем спецификацию Java) из ConditionalExpression полностью через все остальные выражения, но выражение Assignment Expression, наконец, приземляет нас в начале - первичное выражение:
http://es5.github.io/#x11.1
Второй операнд в обоих ваших фрагментов кода выше является первичным выражением:
1
Кончилось все это rigamarole (если я правильно) является то, что в Java, третий операнд тернарного оператора не может быть присвоением, но в JavaScript он может. Вот почему оба ваших примера не работают в Java, но только в JavaScript.
Почему первый работает в JavaScript, но не во втором?
operand1 ? operand2 : operand3;
работает как следующий IIFE код (не фактически, но ниже код иллюстрацией того, как вышеупомянутые работы):
(function() { if (operand0) return operand1; else return operand2;}());
Итак:
false ? 1 : x = 2;
будет (снова, нет фактически - ниже код иллюстративный выше кода):
(function() { if (false) return 1; else return x = 2;}());
Однако в вашем втором фрагменте, при использовании скобок, вы выделите явно условное выражение из «= 2;» :
(false ? 1 : x) = 2;
становится (опять же, не фактически - ниже код иллюстрируют выше код):
(function() { if (false) return 1; else return x;}()) = 2;
В «действует как вызов функции Примера IIFE» поведение трехкомпонентного оператора будет возвращать все, что х и что будет значения, а не ссылка, которая не может быть назначена. Отсюда и ошибка. Это было бы как следующий код (если х === 3):
3 = 2;
Очевидно, что один не может сделать это.
В Java, я считаю, первая дает ошибку, потому что третий оператор не может быть назначением, второй - ошибкой, потому что вы не можете назначить значение (как в JavaScript).
Насколько старшинство операторов, пожалуйста, посмотрите на следующий код:
var x = 3;
console.log(false ? 1 : x); // ?: evaluates to "3"
console.log(false ? 1 : x = 2); // ?: evaluates to "2"
console.log(false ? 1 : x = 2, 4); // ?: evaluates to "2" - "2" and "4" arguments passed to log
console.log((false ? 1 : x = 2, 4)); // ?: evaluates to "4"
Первые два легко понять, если рассматривать с точки зрения IIFE иллюстративного кода выше.
В первой строке x оценивается и условное выражение оценивается в 3 - это легко.
Во второй строке наилучшим образом я могу описать это, что условный оператор (? :) заставляет даже оператор более низкого приоритета «=» оцениваться как полное выражение не потому, что (? :) имеет более высокий приоритет , а потому, что, как указывает спецификация, выражение присваивания, следующее за «:», оценивается (включая часть «= 2») в качестве присваивания. Это поведение выглядит более ясным в операторе return в примерах IIFE выше. По крайней мере, с JavaScript, вы можете иметь назначение не только во втором операнде, но и в третьем условном выражении.
Однако в третьей строке полное выражение присваивания уже найдено в выражении «x = 2», а тернарный оператор использует его как полный третий операнд, а оператор «,» имеет более низкий приоритет, чем любой другой, мы получаем эквивалент следующего кода:
console.log((false ? 1 : x = 2), 4);
в четвертой строке коды, герметизирующий все выражение в заявлении console.log() в круглых скобках приносит «4' в»: 'тройное выражение как часть третьего операнда.
Следующие jsfiddles демонстрируют вышеуказанное обсуждение с живым кодом. Обратите внимание, что первые два имеют точно такую же ошибку после печати '2' дважды:
FIDDLE1
FIDDLE2
FIDDLE3
Обратите внимание, что [условный оператор] (HTTP: //es5.github .io/# x11.12) возвращает значения, а не ссылки. – Teemu
@Teemu - где _value_ может быть ссылкой. Например, '(false? Func1: func2)();' – nnnnnn
@nnnnnn. Вы правы с этим, хотя OP имеет только переменную в примере. На самом деле вы упомянули об этом и в своем ответе, просто плохо читаете для меня ... – Teemu