Простой способ понять вложенные троичные операторы?
Существует ли простая эвристика для понимания того, как читать вложенные троичные операторы? Я сталкивался с этим в чьем-то исходном коде и не могу это сделать. Простая троичная легко:
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
,