カンマ演算子は、JavaScript や C++ などの C 系言語ではあまり知られていない演算子の 1 つです。基本的に、一連の式を区切って、最後の式の結果のみを返します。
const a = 1; const b = 2; const c = 3; const result = (a, b, c, 4, 5, 6, true); console.log(result); // true
if (false, true) console.log('hello'); // hello
そのとき、次の疑問が生じるのは自然です: 複数の式を 1 行に詰め込むのが役立つのはいつですか? さらに、たとえそれが便利だったとしても、なぜカンマで区切られた一連の式を (1 行に詰め込む必要があるのでしょうか)単一行)は、セミコロンで区切られた一連のステートメント(複数行にわたる)よりも読みやすく保守しやすいでしょうか?どちらを優先すべきか?
これらは私が何年も答えられずに苦労してきた質問ですが、今ようやく答えが見つかったと思います。この記事では、カンマ演算子に関する説得力のあるケース (おそらく率直に言って唯一のケース) を紹介します。
まず条件付き三項演算子について話しましょう。以下に示すように、条件が真実であれば、値を評価します。それ以外の場合は、別のものを評価します。ブランチは条件が満たされた場合にのみ実行されるため、ここでは「評価」というキーワードが強調されています。
const result = condition ? value : another;
ほとんどの場合、それはきちんとしていて美しいです。ただし、条件値を返す前の分岐間で、より複雑なロジックを実行する必要がある場合は、問題が発生します。この時点で、私たちは次のような残念な倒錯に頼ることになります:
let result; // Uninitialized! Yikes! if (condition) { // Do some complex stuff in between... doSomething(); // ... result = value; // Actual Assignment } else { // Do other complex stuff in between... doAnotherThing(); // ... result = another; // Actual Assignment } // Hopefully we didn't forget to initialize `result`!
この定式化には多くの問題があります。
条件付き 3 項式を使用する場合、この制限を回避する方法があります。コードを関数にリファクタリングするだけです。それは確かに言うは易く行うは難しです。このギミックはすぐに古くなってしまいます!
function computeWrappedValue() { // ... return value; } function computeWrappedAnother() { // ... return another; } // How cumbersome! const result = condition ? computeWrappedValue() : computeWrappedAnother();
式ベースのプログラミング言語 (Rust など) には、より洗練されたソリューションがあります。 if ステートメント を if 式 として再分類することで、各分岐を評価して、後で変数に格納できる値を返すことができます。
// A conditional ternary operator thus looks like this. Each branch // returns a value, which is captured by the `result` variable. // We thus ensure that `result` is always initialized by construction. let result = if condition { value } else { another };
// If we wanted to do something more complex, we use the same syntax. let result = if condition { do_something(); // In Rust, the last expression without a semicolon is the value // that will be "returned" by the overall `if` expression. result } else { do_another_thing(); another };
これを C に似た言語でエミュレートできますか? あなたはおそらく私がこれでどこへ向かうのかずっと前から予想していたと思いますが、そうです!
私たちが望んでいるのは、三項分岐内で値を返す前にステートメントを任意に実行する方法です。幸いなことに、これはまさに、カンマ演算子の用途です。
// Parenthesized for clarity. const result = condition ? (doSomething(), value) // evaluates to `value` : (doAnotherThing(), another); // evaluates to `another`
この定式化の優れた点は、分岐式が必要な場合にのみ評価されるという事実です。式ベースのプログラミング言語の動作を効果的にエミュレートします。アドホックなラッパー関数の時代は終わりました!
しかし残念ながら、 このテクニックでは限界までしかできません。十分に大きい n の場合、n 個のステートメントを 1 行に詰め込むと、すでに独自の関数にリファクタリングされ始めることが想像できます。個人的には、n > の時点ですでに再考していると思います。 3. それ以上のものは可読性の点で疑わしい構造です。
// Maybe we should reconsider here? const result = condition ? (x++, thing = hello(), doSomething(), value) : (++y, thing = world(), doAnotherThing(), another);
// Okay, stop. Definitely turn back now! const result = condition ? ( x++, thing = hello(), doSomething(), doMore(y), doEvenMore(thing), value, ) : ( ++y, thing = world(), doAnotherThing(), doMore(y), doEvenMore(thing), another, ); // Unless, of course, you're fine with this. It kinda does // look like a Rust `if` expression if you squint hard enough.
最後に、コンマ演算子の説得力のあるケース、つまり複雑な条件付き三項演算を見てきました。カンマ演算子は、分岐が短くて優れている場合には威力を発揮しますが、ステートメントが 3 つインライン化されるとすぐに時代遅れになります。その時点で、コードをリファクタリングしたほうがよいでしょう。
では、カンマ演算子を使用する必要がありますか? 正直に言うと...そうです!読みやすいコードは次の読者のことを念頭に置いたものであるため、カンマチェーンが異常に長くない限り、私はこのコーディング スタイルを受け入れ、さらには奨励します。代替手段 (つまり、初期化されていない変数やリファクタリングされたマイクロ関数) を考慮すると、結局のところ、カンマ演算子はそれほど悪くありません。
実際には、私はすでに自分のコードベースにこれらのおかしな見た目のカンマ演算子を散りばめています。公平を期すために言っておきますが、とにかく複数ステートメントの 3 項条件文が必要になることはほとんどありません。しかし、そのとき、私は自分の意図を簡潔に表現するクールなツールを身に着けています。
そのために、コンマ演算子の説得力のあるケースを取り上げます。
以上がカンマ演算子の説得力のあるケースの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。