javascript - 短絡評価 - ruby 三 項 演算 子 省略




JSのネストされた三項演算子の代替 (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';
})();

replへのリンク

私は個人的に三項演算子を愛し、私の謙虚な意見では、複雑な表現を消化するのがとても簡単です。 これを取る:

  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ステートメントに変えたくないのですが、他のオプションがあるかどうかはわかりません。


あなたの選択肢は基本的に以下の通りです:

  1. あなたがしたくないif
  2. if / elseと組み合わせたswitch

私は妥当なルックアップマップオプションを考え出しましたが、かなり早く不合理になりました。

私は#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 、同じ行に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;
}

最後に、私はこれを主張していません B -syntax言語ファミリでJavaScriptのswitchが普通でないという事実を利用することができます。case文はであり、ソースコード順のスイッチ値と一致します。

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;
}

それはどれくらい醜いのですか? :-)


ネストされた三項式で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);

またはdestructuringを介して名前付きパラメータを使用して...

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);


私の好みでは、慎重に構造化されたネストされた三元詞は、

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' ;

私はこれを直前に直面し、Googleの検索で私をここに導いてくれました。私はこれについて最近発見したものを共有したいと思います:

a && b || c

ほぼ同じことです

a ? b : c

bが真実である限り。 bが真実でない場合、あなたはそれを回避することができます

!a && c || b

cが真実ならば。

最初の式は(a && b) || cとして評価されます。 &&||より優先度が高いです 。

bが真理ならば、 bが真実ならばa && ba && bと評価されるので、式はb || c それが真実ならば、 bと評価されるb || c 、ちょうどaと同じa ? b : c a ? b : ca ? b : c真実ならばaが真実でなければ、式は必要に応じてcと評価されc

&&||交互に使用する トリックと? || ステートメントのレイヤーでno-nested-ternary eslintルールをトリックしますが、これは非常にきちんとしています(他の方法がない限りそうすることはお勧めしませんが)。

簡単なデモンストレーション:

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が常に真実である例を選んでちょっと騙しましたが、文字列を設定しているだけならば、これは皮肉なことに真実であってもうまくいくはずです。


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;




eslint