javascript 短絡評価 JSのネストされた三項演算子の代替




ruby 三 項 演算 子 省略 (7)

すべての真理条件が真理値に評価されれば(疑問符とセミコロンの間の値はブール値に強制されると真と評価されます)、偽の式として三項式をfalse戻すことができます。 その後、ビット単位または( || )演算子を使って連鎖して、次の条件をテストし、最後の値を返すことができます。

以下の例では、 "condsXXX"配列は条件を評価した結果を表しています。 "conds3rd"は3番目の条件が真であることをシミュレートし、 "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';

副注釈として、私はそれが良いコードだとは思わないが、それはあなたのような純粋な三項演算子を使用することに非常に近いです...

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

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


直ちに呼び出される関数式を書いて、読みやすくすることができます:

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へのリンク


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


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

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

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


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;

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


私はこれらの場合にswitch(true)ステートメントを使用しています。 私の意見では、この構文はネストされたif / else演算子よりもやや優雅です

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




eslint