Приоритет оператора с троичным оператором Javascript

Я не могу обернуть голову вокруг первой части этого кода ( +=) в сочетании с троичным оператором.

h.className += h.className ? ' error' : 'error'

Я думаю, что этот код работает следующим образом:

h.className = h.className + h.className ? ' error' : 'error'

Но это не правильно, потому что это дает ошибку в моей консоли.

Итак, мой вопрос, как я должен правильно интерпретировать этот код?

7 ответов

Решение
h.className = h.className + (h.className ? ' error' : 'error')

Вы хотите, чтобы оператор работал на h.className Лучше будь конкретнее.
Конечно, никакого вреда не должно быть h.className += ' error', но это другое дело.

Также обратите внимание, что + имеет приоритет над троичным оператором: приоритет оператора JavaScript

Думайте об этом так:

<variable> = <expression> ? <true clause> : <false clause>

Способ выполнения инструкции в основном следующий:

  1. Есть ли <expression> оценивать как истинное, или оно оценивается как ложное?
  2. Если <expression> оценивается как истина, то значение <true clause> назначен на <variable>, <false clause> игнорируется, и следующий оператор выполняется.
  3. Если <expression> оценивается как ложное, то <true clause> игнорируется и значение <false clause> назначен на <variable>,

С этим троичным оператором на этом и других языках важно понимать, что любой код <expression> должен давать логический результат при оценке: true или false.

В случае вашего примера замените "назначенный" в моем объяснении на "добавленный" или аналогичный для любой сокращенной арифметики, которую вы используете, если таковой имеется.

+= делает то, что вы хотите, но в троичном выражении справа от него, он проверяет, h.className это ложь, которая была бы, если бы она была неопределенной. Если это правда (то есть, если имя класса уже указано), то ошибка добавляется с пробелом (т.е. добавляется новый класс), в противном случае он добавляется без пробела.

Код может быть переписан, как вы предлагаете, но вы должны указать, что h.className должен использоваться для сравнения истинности, а не для использования его фактического значения в троичном операторе, поэтому убедитесь, что вы не беспокоитесь о конкатенации значений одновременно с выполнением троичной операции:

h.className = h.className + (h.className ? ' error' : 'error');

Правая сторона = Оператор оценивается слева направо. Так,

g.className = h.className + h.className ? ' error' : 'error';`

эквивалентно

h.className = (h.className + h.className) ? ' error' : 'error';

Быть эквивалентным

h.className += h.className ? ' error' : 'error';

Вы должны отделить троичное выражение в скобках

h.className = h.className + (h.className ? ' error' : 'error');
if (h.className) {
    h.className = h.className + ' error';
} else {
    h.className = h.className + 'error';
}

должен быть эквивалентен:

h.className += h.className ? ' error' : 'error';

Я знаю, что это очень старый вопрос, но я не на 100% доволен ни одним из ответов, поскольку все они кажутся неполными. Итак, здесь мы снова идем от первых принципов:

Общая цель пользователя:

Резюмируя код: "Я хочу добавить error имя класса в строку, необязательно с начальным пробелом, если в строке уже есть имена классов."

Самое простое решение

Как отметил Коби, 5 лет назад наличие лидирующего пробела в именах классов не вызывало проблем с любыми известными браузерами, поэтому самое короткое правильное решение на самом деле было бы:

h.className += ' error';

Это должно было быть реальным ответом на актуальную проблему.


Как бы то ни было, задаваемые вопросы были...

1) Почему это работает?

h.className += h.className ? ' error' : 'error'

Условный / троичный оператор работает как оператор if, который присваивает результат его true или же false пути к переменной.

Так что код работал, потому что он оценивается просто как:

if (h.className IS NOT null AND IS NOT undefined AND IS NOT '') 
    h.className += ' error'
else
    h.className += 'error'

2) и почему это сломалось?

h.className = h.className + h.className ? ' error' : 'error'

Вопрос гласит: "это приводит к ошибке [n] в моей консоли", что может ввести вас в заблуждение, полагая, что код не работает. Фактически следующий код выполняется без ошибок, но он просто возвращает "ошибку", если строка не была пустой, и "ошибку", если строка была пустой и поэтому не отвечала требованиям.

Этот код всегда приводит к строке, которая содержит только ' error' или же 'error' потому что он оценивает этот псевдокод:

if ((h.className + h.className) IS NOT null AND IS NOT undefined AND IS NOT '')
    h.className = ' error'
else
    h.className = 'error'

Причина этого заключается в том, что оператор сложения (+ для простого народа) имеет более высокий "приоритет" (6), чем условный / троичный оператор (15). Я знаю, что цифры появляются в обратном направлении

Приоритет просто означает, что каждый тип оператора в языке оценивается в определенном предопределенном порядке (а не только слева направо).

Ссылка: Приоритет оператора Javascript

Как изменить порядок оценки:

Теперь мы знаем, почему это не помогает, вам нужно знать, как заставить это работать.

Некоторые другие ответы говорят об изменении приоритета, но вы не можете. Приоритет запрограммирован в язык. Это просто фиксированный набор правил... Однако вы можете изменить порядок оценки...

Инструментом в нашем наборе инструментов, который может изменить порядок оценки, является оператор группировки (он же скобки). Это достигается за счет того, что выражения в скобках вычисляются перед операциями вне скобок. Это все, что они делают, но этого достаточно.

Скобки работают просто потому, что они (операторы группировки) имеют более высокий приоритет, чем все другие операторы ("теперь есть уровень 0").

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

h.className = h.className + (h.className ? ' error' : 'error')

Теперь я оставлю этот ответ на ржавчину невидимым среди других:)

Я хотел бы выбрать объяснение Уэйна:

<variable> = <expression> ? <true clause> : <false clause>

Давайте рассмотрим оба случая:

case 1:
h.className += h.className ? 'true' : 'false'     
  • оператор присваивания работает нормально и значение добавляется
  • при первом запуске o / p: false
  • 2-й раз o / p: falsetrue - значения продолжают добавляться

case2: h.className = h.className + h.className? 'true': 'false'

  • результат не такой, как в случае 1
  • при первом запуске o / p: false
  • 2-й раз o / p: false - значения не добавляются

explanation

В приведенном выше коде, случай 1 работает нормально

тогда как case2:

h.className = h.className + h.className ? 'true' : 'false'
is executed as 
 h.className = (h.className + h.className) ? 'true' : 'false'

h.className + h.className => рассматривается как выражение для троичного оператора, так как троичный оператор имеет более высокий приоритет. поэтому всегда результат троичного выражения просто присваивается

Вы должны определить приоритет, используя скобки

Вам нужно определить порядок оценки, который нужно рассмотреть с помощью скобок для случая 2, чтобы работать как случай 1

h.className = h.className + (h.className ? ' error' : 'error')