1

是否有一个简单的启发式来理解如何阅读嵌套的三元运算符?我在某人的源代码中遇到了这个问题,无法理解。一个简单的三元很容易:

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;

Retabbed,它可以看起来像这样,这几乎可以理解(?)

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

3 回答 3

2

对于像这样混乱的事情,你必须从外到内工作。本质上,这映射到的是:

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)运行它,并将输出与原始代码进行比较,以确认它是相同的。

于 2014-04-10T20:09:22.820 回答
2

我认为如果您尝试将其阅读为一系列check this, if true then this, else that.

为此,将?and:运算符放在行的开头可能会更容易,并像流程图上的箭头一样阅读它们,标记为“是”和“否”。例如:

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

可以读作:

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

这仍然不能使这变得非常可读,我同意所有的评论,即这种代码真的应该重写为可读性。

于 2014-04-10T20:11:09.013 回答
2

我必须将其解析为我脑海中的 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.

于 2014-04-10T20:12:19.783 回答