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

dth*_*ree 28 javascript ternary-operator eslint

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

  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';
Run Code Online (Sandbox Code Playgroud)

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

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

T.J*_*der 19

您的替代方案基本上是:

  1. 那个if/ else你不想做
  2. switch联合if/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';
}
Run Code Online (Sandbox Code Playgroud)

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

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';
Run Code Online (Sandbox Code Playgroud)

(我不是在提倡这一点,我从不主张放弃括号或将声明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;
}
Run Code Online (Sandbox Code Playgroud)

最后,我并不是在提倡这一点,你可以利用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;
}
Run Code Online (Sandbox Code Playgroud)

这有多难啊?:-)


And*_*aus 10

根据我的口味,精心构造的嵌套三元组击败所有那些凌乱的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' ;
Run Code Online (Sandbox Code Playgroud)


Yo *_*ita 6

您可以编写一个立即调用的函数表达式,以使其更具可读性:

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';
})();
Run Code Online (Sandbox Code Playgroud)

链接到REPL


Dou*_*urn 5

如果您希望将 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);
Run Code Online (Sandbox Code Playgroud)

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

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)
  )
);
Run Code Online (Sandbox Code Playgroud)

编辑

在 python if 表达式之后建模可能会更清楚,如下所示:

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);
Run Code Online (Sandbox Code Playgroud)

编辑

另一项编辑删除嵌套的 if/else 分支:

const res = { distance: 1, difference: 5 };

const makeResolvedValue = def => {
  const elseProp = () => def;
  return function value() {
    return {
      if: () => ({ else: elseProp, value })
    };
  }
};

const value = def => ({
  if: expr => {
    if (expr) {
      return { else: () => def, value: makeResolvedValue(def) };
    } else {
      return { else: els => els, value };
    }
  }
});

// with branching if needed
const word = value('a').if(res.distance === 0)
  .else(value('b').if(res.distance === 1 && res.difference > 3)
    .else(value('c').if(res.distance === 2 && res.difference > 5)
      .else('d')
    )
  );
console.log(word)

// implicit else option for clarity
const word2 = value('a').if(res.distance === 0)
  .value('b').if(res.distance === 1 && res.difference > 3)
  .value('c').if(res.distance === 2 && res.difference > 5)
  .else('d');

console.log(word2);
Run Code Online (Sandbox Code Playgroud)

  • 嗯,这很有创意:) (2认同)

dha*_*ker 5

我们可以使用 && 和 || 等基本运算符来简化它

let obj = {}

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

// case 1 pass
obj.distance = 0
console.log(checkWord(obj))

// case 2 pass
obj.distance = 1
obj.difference = 4
console.log(checkWord(obj))

// case 3 pass
obj.distance = 2
obj.difference = 6
obj.key = [1,2,3,4,5,6]
console.log(checkWord(obj))

// case 4 fail all cases
obj.distance = -1
console.log(checkWord(obj))
Run Code Online (Sandbox Code Playgroud)