【问题标题】:Easy way to understand nested ternary operators?理解嵌套三元运算符的简单方法?
【发布时间】:2014-04-10 19:25:51
【问题描述】:

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

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;

Retabred,可以是这个样子,几乎可以理解(?)

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

【问题讨论】:

  • 如果我经营动物园,那将永远通过代码审查。
  • 最低限度是缩进,但仍然不可读。
  • 不需要括号:isVisible = isOnScreen &amp;&amp; notHidden ? true : false。但是你为什么要这样做呢?只是isVisible = isOnscreen &amp;&amp; notHidden。但是您的根本问题是基本逻辑是如此扭曲,以至于它将从这里抛出错误直到永远。最好在更高的层次上重构它。
  • 没有争论,@torazaburo。我只是想了解别人代码的意图。
  • 这只是另一种混淆代码的方式。

标签: javascript ternary-operator ternary-tree


【解决方案1】:

如果您尝试将其阅读为check thisif true then thiselse that 的系列,我认为您可能会更幸运。

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

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

可以读作:

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

这仍然不能使它非常可读,我同意所有 cmets 的说法,这种代码真的应该重写为可读性。

【讨论】:

  • 感谢通用解决方案!可能对可能最终来到这里的其他人最有用。
【解决方案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)运行此程序,并将输出与原始代码进行比较,以确认它是相同的。

【讨论】:

  • 你真的认为嵌套的 if-else 语句不那么混乱吗?
  • 不那么“凌乱”?也许不吧。但至少这个版本让弱者可以理解逻辑。
  • @Bergi 这不是很漂亮,但我没有时间为他简化逻辑。马上,我可以看到一些冗余,如果是我自己的问题,我可能会解决它。
  • 另外,一旦采用这种格式,您就可以更容易地看到如何重构它,这就是最终解决这种丑陋的方法。
  • 我不明白这一点。语义完全相同,由于语法开销较少,合理缩进的三元运算符树更具可读性。由于要输入的字符更少,因此重构更容易。
【解决方案3】:

我必须在脑海中将其解析为 if/else 树吗?

是的,因为在这种情况下它一棵树而不是简单的链式操作符。这些很容易理解 :-) 如果没有缩进,这肯定需要重构。

在这种特殊情况下,否定条件也很有帮助,因为它将条件和效果直接放在一起,从而使阅读更容易:

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

我们还可以将重复的 row &gt;= 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 &amp;&amp; row &gt;= actualFrozenRow

【讨论】:

  • 这是一个 +1,用于实际尝试理解代码的作用。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-29
  • 2021-05-27
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
相关资源
最近更新 更多