web-dev-qa-db-ja.com

コンマ演算子はいつ便利ですか?

this 式の「コンマ演算子」に関する質問(,)および MDN docs についてですが、役に立つシナリオは考えられません。

だから、いつコンマ演算子が便利ですか?

73
gdoron

次のコードは、自分で作成しないため、おそらくあまり有用ではありませんが、ミニファイヤはカンマ演算子を使用してコードを縮小できます。例えば:

if(x){foo();return bar()}else{return 1}

になるだろう:

return x?(foo(),bar()):1

? : 演算子を使用できるようになりました。コンマ演算子(ある程度)を使用すると、2つのステートメントを1つのステートメントとして記述できます。

これは便利な圧縮(ここでは39-> 24バイト)を可能にするという点で便利です。


var a, bのカンマがnotであるという事実を強調したいのは、それがexpressionvarstatementsでは、コンマは特別な意味を持ちます。式のa, bは2つの変数を参照し、var a, bの場合ではないbに評価されます。

111
pimvdb

コンマ演算子を使用すると、1つの式が予期される場所に複数の式を配置できます。コンマで区切られた複数の式の結果値は、最後のコンマ区切り式の値になります。

複数の式が期待される状況はそれほど多くなく、カンマ演算子を使用するよりもコードを書くのにそれほど混乱しない方法がないので、私は個人的にそれをあまり使用しません。 1つの興味深い可能性は、複数の変数をインクリメントしたい場合のforループの終わりです。

// j is initialized to some other value
// as the for loop executes both i and j are incremented
// because the comma operator allows two statements to be put in place of one
for (var i = 0; i < items.len; i++, j++) {
    // loop code here that operates on items[i] 
    // and sometimes uses j to access a different array
}

i++, j++は、1つの式が許可される場所に配置できます。この特定のケースでは、複数の式が副作用に使用されるため、複合式が最後の式の値をとることは問題ではありませんが、実際に問題になる場合があります。

32
jfriend00

コンマ演算子のもう1つの用途は、純粋に便宜上、replまたはコンソールで気にしない結果を非表示にすることです。

たとえば、replまたはコンソールで_myVariable = aWholeLotOfText_を評価すると、割り当てたばかりのすべてのデータが出力されます。これはページおよびページである可能性があります。表示しない場合は、代わりに_myVariable = aWholeLotOfText, 'done'_を評価できます。repl/ consoleは「done」と出力します。

オリエルは正しく指摘します カスタマイズされた toString() または get() 関数がこれを有用にすることさえあります。

17
Julian de Bhal

カンマ演算子はJavaScriptに固有ではなく、 CおよびC++ などの他の言語で使用できます。二項演算子として、これは、一般に式である第1オペランドが、第2オペランドに必要な副作用を持っている場合に役立ちます。ウィキペディアの1つの例:

i = a += 2, a + b;

明らかに2つの異なるコード行を書くことができますが、コンマを使用することは別のオプションであり、時には読みやすくなります。

12
taskinoor

私はフラナガンに反対し、コンマは本当に便利で、特にあなたが何をしているのかを知っているときに、より読みやすくエレガントなコードを書くことができると言います:

コンマの使用に関する 非常に詳細な記事 は次のとおりです。

デモンストレーションの証拠のためにそこからいくつかの例:

_function renderCurve() {
  for(var a = 1, b = 10; a*b; a++, b--) {
    console.log(new Array(a*b).join('*'));
  }
}
_

フィボナッチジェネレーター:

_for (
    var i=2, r=[0,1];
    i<15;
    r.Push(r[i-1] + r[i-2]), i++
); 
// 0,1,1,2,3,5,8,13,21,34,55,89,144,233,377
_

JQuery .parent()関数に類似した最初の親要素を見つけます。

_function firstAncestor(el, tagName) {
    while(el = el.parentNode, el && (el.tagName != tagName.toUpperCase()));
    return el;
}

//element in http://ecma262-5.com/ELS5_HTML.htm
var a = $('Section_15.1.1.2'); 

firstAncestor(a, 'div'); //<div class="page">
_
6
shaman.sir

それ以外の実用的な使用方法は見つかりませんでしたが、ここではJames Padolseyがこの テクニックをうまく使用している1つのシナリオがありますwhile IE検出 whileループで:

var ie = (function(){

    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');

    while ( // <-- notice no while body here
        div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
        all[0]
    );

    return v > 4 ? v : undef;

}());

次の2行を実行する必要があります。

div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]

コンマ演算子の内部では、何らかの方法で別々のステートメントを作成することもできますが、両方が評価されます。

5
Sarfraz

JavaScriptでコンマ演算子を使用して間接的に関数を呼び出すと、「奇妙な」ことができます。

ここに長い説明があります: JavaScriptの間接関数呼び出し

この構文を使用して:

(function() {
    "use strict";
  
    var global = (function () { return this || (1,eval)("this"); })();
    console.log('Global === window should be true: ', global === window);
  
    var not_global = (function () { return this })();
    console.log('not_global === window should be false: ', not_global === window);
  
  }());

evalは、直接呼び出された場合と間接的に呼び出された場合の動作が異なるため、グローバル変数にアクセスできます。

4

このようなヘルパーを作成するときに、コンマ演算子が最も役立つことがわかりました。

const stopPropagation = event => (event.stopPropagation(), event);
const preventDefault = event => (event.preventDefault(), event);
const both = compose(stopPropagation, preventDefault);

コンマを||で置き換えることができますまたは&&ですが、関数が返すものを知る必要があります。

それよりも重要なのは、カンマ区切りが通信することですintent-コードは気にしません 、代替案には別の理由があるかもしれません。これにより、理解とリファクタリングが容易になります。関数の戻り値の型が変更されても、上記のコードは影響を受けません。

当然のことながら、他の方法でも同じことを達成できますが、それほど簡単ではありません。 ||の場合そして、&&が一般的な使用法で場所を見つけたので、カンマ演算子も使用できます。

3

最終的に使用する典型的なケースの1つは、オプションの引数解析中です。引数の解析が関数本体を支配しないように、より読みやすく簡潔にできると思います。

/**
 * @param {string} [str]
 * @param {object} [obj]
 * @param {Date} [date]
 */
function f(str, obj, date) {
  // handle optional arguments
  if (typeof str !== "string") date = obj, obj = str, str = "default";
  if (obj instanceof Date) date = obj, obj = {};
  if (!(date instanceof Date)) date = new Date();

  // ...
}
1
Rich Remer

配列があるとしましょう:

arr = [];

Pushをその配列に配置すると、Pushの戻り値、つまり配列の新しい長さではなく、配列自体にほとんど関心がありません。

arr.Push('foo')  // ['foo'] seems more interesting than 1

コンマ演算子を使用して、配列にプッシュし、コンマの最後のオペランドとして配列を指定してから、結果(配列自体)を後続の配列メソッド呼び出しに使用できます。

(arr.Push('bar'), arr.Push('baz'), arr).sort(); // [ 'bar', 'baz', 'foo' ]
1
George Jempty