式()の「コンマ演算子」に関するこの質問,
とそれに関するMDNドキュメントを読みましたが、それが役立つシナリオは考えられません。
では、コンマ演算子はいつ役に立ちますか?
,
オペレーターと関係があるかどうかはわかりません。その行はでも有効ですC#
が、,
演算子はそこに存在しません。
,
は常に,
演算子であるとは限りません(,
C#では決して演算子ではありません)。したがって、C#は、構文の一部として,
自由に使用,
しながら、演算子が不足している可能性があります。
回答:
以下は、自分で記述しないため、おそらくあまり役に立ちませんが、ミニファイアは、コンマ演算子を使用してコードを縮小できます。例えば:
if(x){foo();return bar()}else{return 1}
になります:
return x?(foo(),bar()):1
? :
コンマ演算子(ある程度)では2つのステートメントを1つのステートメントとして記述できるため、この演算子を使用できるようになりました。
これは、きちんとした圧縮(ここでは39-> 24バイト)を可能にするという点で便利です。
のコンマvar a, b
は式内に存在しないため、コンマ演算子ではないという事実を強調したいと思います。カンマはステートメントで特別な意味を持ちます。式では、2つの変数を参照し、に評価されますが、はそうではありません。var
a, b
b
var a, b
if (condition) var1 = val1, var2 = val2;
個人的には、可能な限り角かっこを避けると、コードが読みやすくなると思います。
コンマ演算子を使用すると、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つの式が許可されている場所に配置できることがわかります。この特定のケースでは、複数の式が副作用に使用されるため、複合式が最後の式の値をとることは問題ではありませんが、実際に問題になる場合もあります。
コンマ演算子は、Javascriptで関数型コードを書くときによく役立ちます。
しばらく前にSPA用に作成した次のようなコードを考えてみましょう。
const actions = _.chain(options)
.pairs() // 1
.filter(selectActions) // 2
.map(createActionPromise) // 3
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) // 4
.value();
これはかなり複雑でしたが、実際のシナリオでした。私が何が起こっているのかを説明している間、私と一緒に耐えてください、そしてその過程でコンマ演算子の主張をしてください。
使用して、この関数に渡されるオプションのすべてを離れて取ることpairs
になりますどの{ a: 1, b: 2}
へ[['a', 1], ['b', 2]]
このプロパティペアの配列は、システム内の「アクション」と見なされるものによってフィルタリングされます。
次に、配列の2番目のインデックスは、そのアクションを表すpromiseを返す関数に置き換えられます(を使用してmap
)
最後に、を呼び出すと、reduce
各「プロパティ配列」(['a', 1]
)がマージされて最終オブジェクトに戻ります。
最終結果はoptions
引数の変換バージョンであり、適切なキーのみが含まれ、その値は呼び出し元の関数によって消費可能です。
ただ見て
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})
reduce関数は、空の状態オブジェクト、state
で始まり、キーと値を表す各ペアについて、キーと値のペアにstate
対応するオブジェクトにプロパティを追加した後、関数は同じオブジェクトを返します。ECMAScript 2015の矢印関数構文により、関数本体は式であり、その結果、コンマ演算子を使用すると、簡潔で便利な「反復」関数を使用できます。
個人的には、ECMAScript 2015 + Arrow Functionsを使用してより機能的なスタイルでJavascriptを記述しているときに、多くのケースに遭遇しました。そうは言っても、矢印関数に遭遇する前(質問の執筆時など)は、意図的な方法でコンマ演算子を使用したことはありませんでした。
reduce
.reduce((state, [key, value]) => (state[key] = value, state), {})
。そして、これは答えの目的を損なうことを理解していますが.reduce((state, [key, value]) => Object.assign(state, { [key]: value }), {})
、コンマ演算子の必要性を完全に排除するでしょう。
コンマ演算子のもう1つの使用法は、純粋に便宜のために、replまたはコンソールで気にしない結果を非表示にすることです。
たとえば、担当者myVariable = aWholeLotOfText
またはコンソールで評価すると、割り当てたばかりのすべてのデータが出力されます。これはページとページである可能性があり、表示したくない場合は、代わりに評価することができmyVariable = aWholeLotOfText, 'done'
、repl / consoleは「done」と出力します。
Orielは、カスタマイズされた機能や機能によってこれが役立つ可能性があることを正しく指摘しています†。toString()
get()
コンマ演算子はJavaScriptに固有のものではなく、CやC ++などの他の言語で使用できます。二項演算子として、これは、一般に式である第1オペランドに、第2オペランドに必要な望ましい副作用がある場合に役立ちます。ウィキペディアからの一例:
i = a += 2, a + b;
もちろん、2行の異なるコードを記述できますが、コンマを使用することも別のオプションであり、場合によっては読みやすくなります。
私はFlanaganに同意しません、そして、コンマは本当に便利で、特にあなたが何をしているのかを知っているとき、より読みやすくエレガントなコードを書くことを可能にする、と言います:
ここにあります大幅に詳細な記事コンマの使用上には:
デモンストレーションの証明のためのそこからのいくつかの例:
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">
while ((el = el.parentNode) && (el.tagName != tagName.toUpperCase()))
そのコンテキストでは問題ありません。
それ以外の実用的な使用法は見つかりませんでしたが、JamesPadolseyがwhileループでIE検出にこの手法をうまく使用しているシナリオを次に示します。
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]
そして、コンマ演算子の内部では、どちらも評価されますが、何らかの方法でそれらを別々のステートメントにすることもできます。
do
-while
ループであった可能性があります。
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
直接呼び出された場合と間接的に呼び出された場合では動作が異なるため、グローバル変数にアクセスできます。
このようなヘルパーを作成するときに、コンマ演算子が最も役立つことがわかりました。
const stopPropagation = event => (event.stopPropagation(), event);
const preventDefault = event => (event.preventDefault(), event);
const both = compose(stopPropagation, preventDefault);
カンマは||のいずれかに置き換えることができます。または&&ですが、関数が何を返すかを知る必要があります。
それよりも重要なのは、コンマ区切り文字が意図を伝えることです。コードは左オペランドの評価を気にしませんが、代替手段には別の理由がある場合があります。これにより、理解とリファクタリングが容易になります。関数の戻り値の型が変更されても、上記のコードは影響を受けません。
当然、他の方法でも同じことを達成できますが、それほど簡潔ではありません。||の場合 &&は一般的な使用法の場所を見つけたので、コンマ演算子も同様です。
tap
(ramdajs.com/docs/#tap)。基本的に、副作用を実行してから初期値を返します。関数型プログラミングで非常に便利です:)
私がそれを使用することになった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();
// ...
}
配列があるとしましょう:
arr = [];
push
その配列にアクセスするとき、push
の戻り値、つまり配列の新しい長さに関心があることはめったになく、配列自体に関心があります。
arr.push('foo') // ['foo'] seems more interesting than 1
コンマ演算子を使用すると、配列にプッシュし、配列をコンマの最後のオペランドとして指定し、その結果(配列自体)を後続の配列メソッド呼び出し(一種の連鎖)に使用できます。
(arr.push('bar'), arr.push('baz'), arr).sort(); // [ 'bar', 'baz', 'foo' ]
コンマ演算子を使用できるもう1つの領域は、コードの難読化です。
開発者が次のようなコードを書いたとしましょう。
var foo = 'bar';
今、彼女はコードを難読化することにしました。使用するツールによって、コードが次のように変更される場合があります。
var Z0b=(45,87)>(195,3)?'bar':(54,65)>(1,0)?'':'baz';// Z0b == 'bar'
var i, j, k;
対var i; var j, var k
?