Тернарные операторы с более чем одной переменной

Я познакомился с концепцией тернарных операторов, и довольно просто понять нотацию:

desired_variable = true ? false ? "value1" : "value2";

Однако я не мог понять, почему добавлена ​​вторая переменная, даже если я понимаю ответ. Чтобы использовать классический пример:

var eatsPlants = false;
var eatsAnimals = false;
var category;

category = eatsPlants ? eatsAnimals ? "omnivore" : "herbivore" : eatsAnimals ? "carnivore" : undefined;
console.log(category)

Вот одно наблюдение: если я изменю порядок переменных на приведенный ниже оператор, функция не будет работать:

category = eatsAnimals ? eatsPlants? "carnivore" : undefined : eatsPlants ? "herbivore" : "omnivore";
console.log(category)

Мой вопрос: почему функция не работает, когда условия перевернуты? И как мне выбрать порядок членов, когда у меня есть две или более переменных (и, следовательно, четыре или более результатов)?


person cgobbet    schedule 09.03.2019    source источник
comment
в одной тройке есть только один вопросительный знак и двоеточие, например variable = comparison ? value1 : value2;   -  person Nina Scholz    schedule 09.03.2019
comment
В общем, если ваш тернарный оператор не супер прост, вам, вероятно, следует избегать написания логики в виде тернарного оператора и вместо этого просто использовать if/else. Нет смысла размещать все в одной строке, если вам потребуется больше времени, чтобы прочитать и понять, что происходит.   -  person VLAZ    schedule 09.03.2019
comment
Я согласен с тем, что if/else было бы яснее. Проблема в том, что я пытаюсь получить логическое мышление больше, чем окончательный результат.   -  person cgobbet    schedule 10.03.2019


Ответы (5)


Вы можете понять на этом примере.

x ? ( y ? a : b ) : c
|
|________true   ---> y ? a : b
|
|________false  ---> c
  • сначала проверьте значение x, если оно верно, будет запущено y ? a : b (я добавил () только для удобства чтения)
  • Если оно ложно, оно перейдет к c

Вы можете просто понять это так же, как if/else, если я изменю приведенный выше код на if/else

if(x){
  if(y) {
    return a
  } else {
    return b
} else {
   return c
 }
}
person Code Maniac    schedule 09.03.2019
comment
Спасибо, это мне очень помогло. - person cgobbet; 12.03.2019

Тернарные выражения имеют внутри 3 выражения. Однако, поскольку троичные выражения сами по себе являются выражениями, вы можете поместить троичные выражения внутрь других троичных выражений. Тернарные выражения в приведенном выше примере выглядят настолько запутанными, потому что они представляют собой несколько вложенных тернарных выражений. Эта путаница может быть лучше устранена с помощью форматирования и использования круглых скобок:

var eatsPlants = false;
var eatsAnimals = false;
var category = null;

category =
  (eatsPlants ?
    (eatsAnimals ? "omnivore" : "herbivore")
    :
    (eatsAnimals ? "carnivore" : undefined)
  );
console.log(category);

person pretzelhammer    schedule 09.03.2019

Чтобы получить правильный результат, вы можете сгруппировать тройки и поддерживать один и тот же уровень решений.

var eatsPlants = false,
    eatsAnimals = false,
    category = eatsPlants
        ? eatsAnimals
            ? "omnivore"
            : "herbivore"
        : eatsAnimals
            ? "carnivore"
            : undefined;

console.log(category);

person Nina Scholz    schedule 09.03.2019

Вы не можете изменить порядок между then и else частями, так как это влияет на результат (если вы также не отмените условие). Однако вы можете изменить вложение и написать либо

category = eatsPlants
  ? eatsAnimals
      ? "omnivore"
      : "herbivore"
  : eatsAnimals
      ? "carnivore"
      : undefined;

or

category = eatsAnimals
  ? eatsPlants
      ? "omnivore"
      : "carnivore"
  : eatsPlants
      ? "herbivore"
      : undefined;
person Bergi    schedule 09.03.2019

Тернарная операция всегда принимает три операнда, например:

inputExpression ? outputExpressionIfTrue : outputExpressionIfFalse

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

var eatsPlants = false;
var eatsAnimals = false;
var category;

category = eatsPlants
  ? (eatsAnimals ? "omnivore" : "herbivore") // doesn't run because eatsPlants is false
  : (eatsAnimals ? "carnivore" : undefined); //returns undefined because eatsAnimals is false 
console.log(category);

category = eatsAnimals
 ? (eatsPlants ? "carnivore" : undefined) // doesn't run because eatsAnimals is false
 : (eatsPlants ? "herbivore" : "omnivore"); // returns "omnivore" because eatsPlants is false
console.log(category);

Обратите внимание, что для обработки информации о категориях вещей с похожими свойствами может быть полезно использовать такие объекты, как:

const carnivore =  {
  eatsPlants: false,
  eatsAnimals: true
};
const herbivore =  {
  eatsPlants: true,
  eatsAnimals: false
};
const omnivore =  {
  eatsPlants: true,
  eatsAnimals: true
};

console.log("carnivore:");
console.log("  eatsPlants: " + carnivore.eatsPlants);
console.log("  eatsAnimals: " + carnivore.eatsAnimals);
console.log("herbivore:");
console.log("  eatsPlants: " + herbivore.eatsPlants);
console.log("  eatsAnimals: " + herbivore.eatsAnimals);
console.log("omnivore:");
console.log("  eatsPlants: " + omnivore.eatsPlants);
console.log("  eatsAnimals: " + omnivore.eatsAnimals);  

person Cat    schedule 09.03.2019