Простой способ понять вложенные троичные операторы?

Существует ли простая эвристика для понимания того, как читать вложенные троичные операторы? Я сталкивался с этим в чьем-то исходном коде и не могу это сделать. Простая троичная легко:

isRed = color == 'red' ? true : false

Но как вы читаете следующее? Могу ли я просто выровнять первое с последним, а второе - с вторым по последнему, или я должен разобрать это в дереве if/else в моей голове?

var offset =
  ( hasFrozenRows )
    ? ( options.frozenBottom )
    ? ( row >= actualFrozenRow )
    ? ( h < viewportTopH )
    ? ( actualFrozenRow * options.rowHeight )
    : h
    : 0
    : ( row >= actualFrozenRow )
    ? frozenRowsHeight
    : 0
    : 0;

Перефразировано, это может выглядеть так, что почти понятно (?)

      var offset =
        ( hasFrozenRows ) ?
          ( options frozenBottom ) ?
            ( row >= actualFrozenRow ) ?
              ( h < viewportTopH ) ?
                ( actualFrozenRow * options.rowHeight )
                :
                h
              :
              0
            :
            ( row >= actualFrozenRow ) ?
              frozenRowsHeight
              :
              0
            :
            0;

3 ответа

Решение

Я думаю, вам повезет больше, если вы попытаетесь прочитать это как серию check this, if true then this, else that,

Для этого может быть проще поставить ? а также : операторы в начале строк, и читайте их, как если бы они были стрелками на блок-схеме, помеченными "да" и "нет". например:

cond1 
  ? cond2 
    ? cond3 
      ? res1 
      : res2
    : res3
  : res4

Который может быть прочитан как:

cond1?
  yes -> is cond2 
    yes -> is cond3?
      yes -> res1 
      no -> res2
    no -> res3
  no -> res4

Это все еще не делает это очень читабельным, и я согласен со всеми комментариями о том, что этот вид кода действительно должен быть переписан, чтобы быть читаемым.

Для чего-то беспорядочного, подобного этому, вы должны поработать извне. По сути, это то, к чему это относится:

if ( hasFrozenRows ) {
  if ( options.frozenBottom ) {
    if ( row >= actualFrozenRow ) {
      if ( h < viewportTopH ) {
        return ( actualFrozenRow * options.rowHeight )
      } else {
        return h;
      }
    } else {
      return 0;
    }
  } else {
    if ( row >= actualFrozenRow ) {
      return frozenRowsHeight
    } else {
      return 0
    }
  }
} else {
  return 0;
}

И я думал, что старый кодекс, с которым я работал, был кошмаром...

Я рекомендую запустить его через тестер модулей, например, Jasmine, и сравнить выходные данные с исходным кодом, чтобы убедиться, что он такой же.

я должен разобрать это в дерево if/else в моей голове?

Да, потому что в данном случае это дерево, а не просто цепочечные операторы. Это было бы легко понять:-) Без отступов это определенно требует рефакторинга.

В этом конкретном случае также было бы полезно отменить условия, делая чтение намного проще, так как это ставит условие и эффект непосредственно рядом друг с другом:

var offset = (!hasFrozenRows)
               ? 0
               : (!options.frozenBottom)
                 ? (row < actualFrozenRow)
                   ? 0
                   : (h < viewportTopH)
                     ? actualFrozenRow * options.rowHeight
                     : h
                 : (row >= actualFrozenRow)
                   ? frozenRowsHeight
                   : 0;

Мы также могли бы переместить дубликат row >= actualFrozenRow Сравнение на один уровень выше:

var offset = (!hasFrozenRows)
             ? 0
             : (row < actualFrozenRow)
               ? 0
               : (!options.frozenBottom)
                 ? frozenRowsHeight
                 : (h < viewportTopH)
                   ? actualFrozenRow * options.rowHeight
                   : h;

... что на самом деле делает его совершенно понятным, даже если не отрицается:

var offset = ( hasFrozenRows )
             ? ( row >= actualFrozenRow )
               ? ( options.frozenBottom )
                 ? ( h < viewportTopH )
                   ? actualFrozenRow * options.rowHeight
                   : h
                 : frozenRowsHeight
               : 0
             : 0;

Теперь вы также можете видеть, что вы можете объединить первые два условия в hasFrozenRows && row >= actualFrozenRow,

Другие вопросы по тегам