Javascript 理解嵌套三元运算符的简单方法?

Javascript 理解嵌套三元运算符的简单方法?,javascript,ternary-operator,ternary-tree,Javascript,Ternary Operator,Ternary Tree,有没有一个简单的启发式方法来理解如何读取嵌套的三元运算符? 我在某人的源代码中遇到了这一点,但我无法理解。简单的三元结构很容易: isRed = color == 'red' ? true : false 但是你如何阅读下面的内容呢?我能把第一个和最后一个排成一行,第二个和倒数第二个排成一行吗?或者我必须把它解析成我头脑中的if/else树吗 var offset = ( hasFrozenRows ) ? ( options.frozenBottom ) ? ( row

有没有一个简单的启发式方法来理解如何读取嵌套的三元运算符? 我在某人的源代码中遇到了这一点,但我无法理解。简单的三元结构很容易:

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;

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

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

我想如果你试着把它看作一系列的检查,如果是真的,那么这个,否则那个,你会有更多的运气

对于这一点,可能更容易将?和:操作员位于行的开头,并将其视为流程图上的箭头,标记为是和否。例如:

cond1 
  ? cond2 
    ? cond3 
      ? res1 
      : res2
    : res3
  : res4
可以理解为:

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

这仍然不能使它具有很好的可读性,我同意所有的评论,认为这种代码应该被重写为可读的

我想如果你试着把它看作一系列的检查,如果是真的,那么这个,否则那个,你会有更多的运气

对于这一点,可能更容易将?和:操作员位于行的开头,并将其视为流程图上的箭头,标记为是和否。例如:

cond1 
  ? cond2 
    ? cond3 
      ? res1 
      : res2
    : res3
  : res4
可以理解为:

cond1?
  yes -> is cond2 
    yes -> is cond3?
      yes -> res1 
      no -> res2
    no -> res3
  no -> res4
这仍然不能使它具有很好的可读性,我同意所有的评论,认为这种代码应该被重写为可读的

我必须将其解析为我头脑中的if/else树吗

var offset =
  ( hasFrozenRows )
    ? ( options.frozenBottom )
    ? ( row >= actualFrozenRow )
    ? ( h < viewportTopH )
    ? ( actualFrozenRow * options.rowHeight )
    : h
    : 0
    : ( row >= actualFrozenRow )
    ? frozenRowsHeight
    : 0
    : 0;
是的,因为在这种情况下,它是一棵树,而不是简单的链式操作符。这些很容易理解:-如果没有缩进,这肯定需要重构

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

var offset = (!hasFrozenRows)
               ? 0
               : (!options.frozenBottom)
                 ? (row < actualFrozenRow)
                   ? 0
                   : (h < viewportTopH)
                     ? actualFrozenRow * options.rowHeight
                     : h
                 : (row >= actualFrozenRow)
                   ? frozenRowsHeight
                   : 0;
…这实际上使它完全可以理解,即使没有否定:

var offset = ( hasFrozenRows )
             ? ( row >= actualFrozenRow )
               ? ( options.frozenBottom )
                 ? ( h < viewportTopH )
                   ? actualFrozenRow * options.rowHeight
                   : h
                 : frozenRowsHeight
               : 0
             : 0;
您现在还可以看到,您可以将前两个条件合并为hasFrozenRows&&row>=actualFrozenRow

我必须将其解析为我头脑中的if/else树吗

var offset =
  ( hasFrozenRows )
    ? ( options.frozenBottom )
    ? ( row >= actualFrozenRow )
    ? ( h < viewportTopH )
    ? ( actualFrozenRow * options.rowHeight )
    : h
    : 0
    : ( row >= actualFrozenRow )
    ? frozenRowsHeight
    : 0
    : 0;
是的,因为在这种情况下,它是一棵树,而不是简单的链式操作符。这些很容易理解:-如果没有缩进,这肯定需要重构

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

var offset = (!hasFrozenRows)
               ? 0
               : (!options.frozenBottom)
                 ? (row < actualFrozenRow)
                   ? 0
                   : (h < viewportTopH)
                     ? actualFrozenRow * options.rowHeight
                     : h
                 : (row >= actualFrozenRow)
                   ? frozenRowsHeight
                   : 0;
…这实际上使它完全可以理解,即使没有否定:

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

您现在还可以看到,您可能会将前两个条件合并为hasFrozenRows&&row>=actualFrozenRow。

如果我运行zoo,它将永远不会通过代码审查。最小值是缩进,但仍然无法读取。不需要括号:isVisible=isOnScreen&¬Hidden?对:错。但你为什么要这么做?它只是isVisible=isOnscreen&¬Hidden。但你的根本问题是,基本逻辑是如此扭曲,从这里到永远都会抛出错误。最好在更高的层次上重构它。这里没有争论,@torazaburo。我只是想了解其他人代码的意图。这只是另一种观察代码的方式。如果我运行了zoo,那将永远无法通过代码审查。最低要求是缩进,但仍然无法读取。不需要括号:isVisible=isOnScreen&¬Hidden?对:错。但你为什么要这么做?它只是isVisible=isOnscreen&¬Hidden。但你的根本问题是,基本逻辑是如此扭曲,从这里到永远都会抛出错误。最好在更高的层次上重构它。这里没有争论,@torazaburo。我只是想理解其他人代码的意图。这只是另一种遵守代码的方式。你真的认为嵌套的if-else语句不那么凌乱吗?不那么凌乱吗?也许不是。但至少这个版本让一个弱小的人可以理解这个逻辑。@Bergi它不漂亮,但我没有时间让他把逻辑简化。一开始,我就可以看到一些冗余,如果这是我自己的问题,我可能会修复它。而且,一旦它以这种格式出现,你可以更容易地看到如何重构它,这就是这种丑陋将如何发生的
艾丽得到解决,我不明白这一点。语义是完全相同的,合理缩进的三元运算符树由于语法开销较小而更具可读性。因为要输入的字符更少,所以重构更容易。你真的认为嵌套的if-else语句不那么凌乱吗?不那么凌乱吗?也许不是。但至少这个版本让一个弱小的人可以理解这个逻辑。@Bergi它不漂亮,但我没有时间让他把逻辑简化。一开始,我可以看到一些冗余,如果这是我自己的问题,我可能会修复它。而且,一旦它以这种格式出现,你可以更容易地看到如何重构它,这就是如何最终解决这个丑陋的问题。我不明白这一点。语义是完全相同的,合理缩进的三元运算符树由于语法开销较小而更具可读性。因为要输入的字符更少,所以重构更容易。下面是一个+1,用于实际理解代码的功能:下面是一个+1,用于实际理解代码的功能:感谢您提供的通用解决方案!可能对其他可能在这里结束的人最有用。感谢您提供的通用解决方案!可能对其他可能在这里结束的人最有用。