首页 文章

替代JS中的嵌套三元运算符

提问于
浏览
18

我个人喜欢三元运算符,并且在我看来,他们使复杂的表达式很容易消化 . 拿这个:

word = (res.distance === 0) ? 'a'
    : (res.distance === 1 && res.difference > 3) ? 'b'
    : (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c'
    : 'd';

但是在我们项目的ESLINT规则中,嵌套的三元运算符是被禁止的,所以我必须摆脱上述情况 .

我试图找出这种方法的替代方案 . 我真的不想把它变成一个巨大的if / else语句,但不知道是否还有其他选择 .

8 回答

  • 0

    您可以编写immediately invoked function expression以使其更具可读性:

    const word = (() =>  {
      if (res.distance === 0) return 'a';
      if (res.distance === 1 && res.difference > 3) return 'b';
      if (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) return 'c';
      return 'd';
    })();
    

    Link to repl

  • 17

    您的替代方案基本上是:

    你不想做

    • 那个 if / else

    • A switchif / else 合并

    我试图提出一个合理的查找映射选项,但它很快就变得不合理了 .

    我会去#1,它不是那么大:

    if (res.distance == 0) {
        word = 'a';
    } else if (res.distance == 1 && res.difference > 3) {
        word = 'b';
    } else if (res.distance == 2 && res.difference > 5 && String(res.key).length > 5) {
        word = 'c';
    } else {
        word = 'd';
    }
    

    如果所有的大括号和垂直大小都打扰你,没有它们,它几乎与条件运算符版本一样简洁:

    if (res.distance == 0) word = 'a';
    else if (res.distance == 1 && res.difference > 3) word = 'b';
    else if (res.distance == 2 && res.difference > 5 && String(res.key).length > 5) word = 'c';
    else word = 'd';
    

    (我不是在提倡这一点,我从不主张在同一条线上放下大括号或将声明放在 if 之后,但其他人则有不同的风格观点 . )

    在我看来,#2更笨重,但这可能更像是一种风格评论而不是其他任何东西:

    word = 'd';
    switch (res.distance) {
        case 0:
            word = 'a';
            break;
        case 1:
            if (res.difference > 3) {
                word = 'b';
            }
            break;
        case 2:
            if (res.difference > 5 && String(res.key).length > 5) {
                word = 'c';
            }
            break;
    }
    

    最后,我赞成这一点,你可以利用JavaScript的 switchB -syntax语言族中不常见的事实: case 语句可以是表达式,并且与源代码顺序中的switch值匹配:

    switch (true) {
        case res.distance == 0:
            word = 'a';
            break;
        case res.distance == 1 && res.difference > 3:
            word = 'b';
            break;
        case res.distance == 2 && res.difference > 5 && String(res.key).length > 5:
            word = 'c';
            break;
        default:
            word = 'd';
            break;
    }
    

    这有多难啊? :-)

  • 0

    根据我的口味,精心构造的嵌套三元组击败所有那些凌乱的ifs和开关:

    const isFoo = res.distance === 0;
    const isBar = res.distance === 1 && res.difference > 3;
    const isBaz = res.distance === 2 && res.difference > 5 && String(res.key).length > 5;
    
    const word =
      isFoo ? 'a' :
      isBar ? 'b' :
      isBaz ? 'c' :
              'd' ;
    
  • 2

    如果您所有的真实条件都评估为真值(因此,如果强制转换为布尔值,则问号和分号之间的值将评估为真),您可以使三元表达式返回 false 作为虚假表达式 . 然后你可以用bitwise或( || )运算符链接它们来测试下一个条件,直到你返回默认值的最后一个条件 .

    在下面的示例中,“condsXXX”数组表示评估条件的结果 . “conds3rd”模拟第三个条件为真,“condsNone”模拟没有条件成立 . 在现实生活中的代码中,您在赋值表达式中具有“内联”条件:

    var conds3rd = [false, false, true];
    var condsNone = [false, false, false];
    
    var val3rd = (conds3rd[0] ? 1 : false) ||
      (conds3rd[1] ? 2 : false) ||
      (conds3rd[2] ? 3 : 4);
    
    var valNone = (condsNone[0] ? 1 : false) ||
      (condsNone[1] ? 2 : false) ||
      (condsNone[2] ? 3 : 4);
    
    alert(val3rd);
    alert(valNone);
    

    您的示例最终可能如下所示:

    word = ((res.distance === 0) ? 'a' : false) ||
        ((res.distance === 1 && res.difference > 3) ? 'b' : false) ||
        ((res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c' : 'd';
    

    作为旁注,我觉得它不是一个好看的代码,但它非常接近于使用像你渴望做的纯三元运算符......

  • 2
    word = (res.distance === 0) ? 'a'
    : (res.distance === 1 && res.difference > 3) ? 'b'
    : (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c'
    : 'd';
    

    这是一个较老的问题,但这就是我要做的...我会从默认情况开始,然后根据需要更改变量或传递它 .

    var word = 'd';
    word = (res.distance === 0) ? 'a' : word;
    word = (res.distance === 1 && res.difference > 3) ? 'b' : word
    word = (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c' : word;
    
  • 2

    如果您希望将const与嵌套三元表达式一起使用,则可以使用函数表达式替换三元组 .

    const res = { distance: 1, difference: 5 };
    
    const branch = (condition, ifTrue, ifFalse) => condition?ifTrue:ifFalse;
    const word = branch(
      res.distance === 0,    // if
      'a',                   // then
      branch(                // else
        res.distance === 1 && res.difference > 3,   // if
        'b',                                        // then
        branch(                                     // else
          res.distance === 2 && res.difference > 5,   // if
          'c',                                        // then
          'd'                                         // else
        )
      )
    );
    
    console.log(word);
    

    或通过解构使用命名参数...

    const branch2 = function(branch) {
      return branch.if ? branch.then : branch.else;
    }
    
    const fizzbuzz = function(num) {
      return branch2({
        if: num % 3 === 0 && num % 5 === 0,
        then: 'fizzbuzz',
        else: branch2({
            if: num % 3 === 0,
            then: 'fizz',
            else: branch2({
              if: num % 5 === 0,
              then: 'buzz',
              else: num
            })
          })
      });
    }
    
    console.log(
      [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16].map(
        cv => fizzbuzz(cv)
      )
    );
    

    ...编辑:在python之后对它进行建模可能更清楚如果这样的表达式:

    const res = { distance: 1, difference: 5 };
    
    const maybe = def => ({
      if: expr => {
        if (expr) {
          return { else: () => def };
        } else {
          return { else: els => els };
        }
      }
    });
    const word = maybe('a').if(res.distance === 0).else(
      maybe('b').if(res.distance === 1 && res.difference > 3).else(
        maybe('c').if(res.distance === 2 && res.difference > 5).else('d')
      )
    );
    console.log(word);
    
  • 1

    我最近也面对这个问题,谷歌搜索引领我到这里,我想分享一些我最近发现的关于此事的内容:

    a && b || c

    几乎是一样的

    a ? b : c

    只要 b 是真实的 . 如果 b 不是真的,你可以使用它来解决它

    !a && c || b

    如果 c 是真的 .

    第一个表达式被评估为 (a && b) || c ,因为 && 的优先级高于 || .

    如果 a 是真实的,那么 a && b 将评估为 b 如果 b 是真实的,那么表达式变为 b || c ,如果它是真实的则评估为 b ,就像 a ? b : c 如果 a 是真实的,如果 a 不是真实的那么表达式将评估为根据需要 c .

    在语句层中 &&|| 技巧和 ? 以及 || 之间交替使用了非嵌套三元符号规则,这非常简洁(尽管除非没有别的办法,否则我不建议这样做) .

    快速演示:

    true ? false ? true : true ? false : true ? true ? true : false : true : true
    // which is interpreted as
    true ? (false ? true : (true ? false : (true ? (true ? true : false) : true))) : true
    // now with the trick in alternate levels
    true ? (false && true || (true ? false : (true && (true ? true : false) || true))) : true
    // all of these evaluate to false btw
    

    我实际上通过选择 b 总是真实的例子来作弊,但如果你只是设置字符串,那么这应该工作正常,因为即使 '0' 具有讽刺意味 .

  • 9

    我一直在为这些案例使用switch(true)语句 . 在我看来,这种语法感觉稍微优雅一点比嵌套的if / else运算符

    switch (true) {
      case condition === true :
        //do it
        break;
      case otherCondition === true && soOn < 100 :
        // do that
        break;
    }
    

相关问题