Wann ist der Kommaoperator nützlich?

86

Ich habe diese Frage zum "Komma-Operator" in expression ( ,) und in den MDN-Dokumenten darüber gelesen , kann mir aber kein Szenario vorstellen, in dem dies nützlich ist.

Wann ist der Kommaoperator nützlich?

Gdoron unterstützt Monica
quelle
2
var i, j, k;vs var i; var j, var k?
Salman A
15
@ SalmanA. Ich bin mir nicht sicher, ob es etwas mit dem ,Betreiber zu tun hat . Diese Zeile ist auch in gültig C#, aber der ,Operator existiert dort nicht.
Gdoron unterstützt Monica
2
@ SalmanA. Ich tat. Ich habe es nicht gefunden, erleuchte mich ...
Gdoron unterstützt Monica am
5
@SalmanA a ,ist nicht immer der ,Operator (und es ist nie der ,Operator in C #). Daher kann C # einen ,Operator fehlen , während er ,als Teil der Syntax noch frei verwendet wird .
Seth Carnegie
8
Ich denke, die Antworten hier haben die Tatsache zusammengefasst, dass das ,nicht weit verbreitet ist (und nicht jedes Vorkommen von a ,der Kommaoperator ist) . Sie können es jedoch und ein Array ausleihen, um einen Variablentausch inline durchzuführen, ohne eine temporäre Variable zu erstellen. Wenn Sie die Werte von aund tauschen möchten b, können Sie dies tun a = [b][b = a,0]. Dadurch wird der Strom bin das Array eingefügt. Die zweite []ist die Eigenschaftszugriffsnotation. Der Index zugegriffen wird 0, aber nicht , bevor die Zuordnung azu b, die nun sicher ist , da bin dem Array zurückgehalten wird. Das ,lässt uns die mehreren Ausdrücke in der machen [].

Antworten:

127

Das Folgende ist wahrscheinlich nicht sehr nützlich, da Sie es nicht selbst schreiben, aber ein Minifier kann Code mithilfe des Komma-Operators verkleinern. Beispielsweise:

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

würde werden:

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

Der ? :Operator kann jetzt verwendet werden, da der Kommaoperator (bis zu einem gewissen Grad) zulässt, dass zwei Anweisungen als eine Anweisung geschrieben werden.

Dies ist insofern nützlich, als es eine ordentliche Komprimierung ermöglicht (39 -> 24 Bytes hier).


Ich möchte die Tatsache hervorheben , dass das Komma in var a, bist nicht der Komma - Operator , weil sie nicht innerhalb eines existiert Ausdruck . Das Komma hat in var Aussagen eine besondere Bedeutung . a, bin einem Ausdruck würde sich auf die beiden Variablen beziehen und auswerten b, was für nicht der Fall ist var a, b.

pimvdb
quelle
3
Wie hast du darüber gedacht? Hast du es wo gelesen? Wird es wirklich benutzt?
Gdoron unterstützt Monica
16
Ich habe neulich nur mit Closure Compiler herumgespielt, um zu sehen, was es tatsächlich tut, und ich habe diese Ersetzung bemerkt.
Pimvdb
2
Eine ähnliche Verwendung, die meiner Meinung nach in Ihrem Code nützlich ist, besteht darin, mehrere Variablen in einer Inline-if-Anweisung zuzuweisen. Zum Beispiel: if (condition) var1 = val1, var2 = val2;Ich persönlich denke, dass das Vermeiden von Klammern den Code lesbarer macht, wenn dies möglich ist.
Aidiakapi
2
Ich benutze den Komma-Operator nur dann, wenn ich Ausdrücken (foo => (console.log ('foo', foo), foo)) Protokollanweisungen hinzufüge oder wenn ich mit reduzierten Iteraten zu schlau werde . (pairs.reduce ((acc, [k, v]) => (acc [k] = v, acc), {}))
Joseph Sikorski
38

Mit dem Komma-Operator können Sie mehrere Ausdrücke an einer Stelle platzieren, an der ein Ausdruck erwartet wird. Der resultierende Wert mehrerer durch Komma getrennter Ausdrücke ist der Wert des letzten durch Kommas getrennten Ausdrucks.

Ich persönlich benutze es nicht sehr oft, weil es nicht so viele Situationen gibt, in denen mehr als ein Ausdruck erwartet wird und es keine weniger verwirrende Möglichkeit gibt, den Code zu schreiben, als den Komma-Operator zu verwenden. Eine interessante Möglichkeit besteht am Ende einer forSchleife, wenn mehr als eine Variable inkrementiert werden soll:

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

Hier sehen Sie, dass i++, j++dies an einer Stelle platziert werden kann, an der ein Ausdruck zulässig ist. In diesem speziellen Fall werden die mehreren Ausdrücke für Nebeneffekte verwendet, sodass es keine Rolle spielt, dass die zusammengesetzten Ausdrücke den Wert des letzten annehmen, aber es gibt andere Fälle, in denen dies tatsächlich von Bedeutung sein könnte.

jfriend00
quelle
36

Der Komma-Operator ist häufig nützlich, wenn Sie Funktionscode in Javascript schreiben.

Betrachten Sie diesen Code, den ich vor einiger Zeit für ein SPA geschrieben habe und der ungefähr Folgendes enthielt

const actions = _.chain(options)
                 .pairs() // 1
                 .filter(selectActions) // 2
                 .map(createActionPromise) // 3
                 .reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) // 4
                 .value();

Dies war ein ziemlich komplexes, aber reales Szenario. Nehmen Sie mich mit, während ich erkläre, was passiert, und machen Sie sich dabei für den Komma-Operator stark.


Dies verwendet die Verkettung von Underscore an

  1. Nehmen Sie an diese Funktion übergeben alle Optionen auseinander mit pairs welcher verwandeln wird { a: 1, b: 2}in[['a', 1], ['b', 2]]

  2. Dieses Array von Eigenschaftspaaren wird gefiltert, nach denen im System als "Aktionen" angesehen wird.

  3. Dann wird der zweite Index im Array durch eine Funktion ersetzt, die ein Versprechen zurückgibt, das diese Aktion darstellt (using map).

  4. Schließlich führt der Aufruf von reducejedes "Eigenschaftsarray" ( ['a', 1]) wieder zu einem endgültigen Objekt zusammen.

Das Endergebnis ist eine transformierte Version des optionsArguments, die nur die entsprechenden Schlüssel enthält und deren Werte von der aufrufenden Funktion verwendet werden können.


Nur anschauen

.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})

Sie können sehen, dass die Reduzierungsfunktion mit einem leeren Statusobjekt beginnt. stateFür jedes Paar, das einen Schlüssel und einen Wert darstellt, gibt die Funktion dasselbe stateObjekt zurück, nachdem dem Objekt, das dem Schlüssel / Wert-Paar entspricht, eine Eigenschaft hinzugefügt wurde. Aufgrund der Pfeilfunktionssyntax von ECMAScript 2015 ist der Funktionskörper ein Ausdruck. Daher ermöglicht der Komma-Operator eine präzise und nützliche "iteratee" -Funktion.

Persönlich bin ich beim Schreiben von Javascript in einem funktionaleren Stil mit ECMAScript 2015 + Arrow Functions auf zahlreiche Fälle gestoßen. Allerdings hatte ich den Komma-Operator nie absichtlich verwendet, bevor ich auf Pfeilfunktionen gestoßen bin (z. B. zum Zeitpunkt des Schreibens der Frage).

Syynth
quelle
1
Dies ist die einzig wirklich nützliche Antwort in Bezug darauf, wie / wann ein Programmierer den Komma-Operator verwenden kann. Sehr nützlich, besonders inreduce
hgoebl
1
Mit ES6 + sollte dies die akzeptierte Antwort sein.
Ardee Aram
Schöne Antwort, aber wenn ich etwas Lesbareres vorschlagen darf : .reduce((state, [key, value]) => (state[key] = value, state), {}). Und mir ist klar, dass dies den Zweck der Antwort zunichte macht, aber .reduce((state, [key, value]) => Object.assign(state, { [key]: value }), {})die Notwendigkeit für den Kommaoperator vollständig eliminieren würde.
Patrick Roberts
Obwohl Object.assign heutzutage wahrscheinlich eher idiomatisch ist oder nur der Spread-Operator, bin ich mir nicht sicher, ob sie zu dieser Zeit weit verbreitet waren. Ich möchte auch darauf hinweisen, dass der Komma-Operator zwar etwas dunkler ist, dies jedoch in Situationen, in denen die Datenmenge sehr groß ist, viel weniger Müll erzeugen kann. Die Destrukturierung würde sicherlich die Lesbarkeit verbessern!
Syynth
18

Eine andere Verwendung für den Komma-Operator besteht darin, Ergebnisse, die Sie nicht interessieren, nur aus praktischen Gründen in der Replik oder Konsole auszublenden.

Wenn Sie beispielsweise myVariable = aWholeLotOfTextin der Replik oder Konsole auswerten , werden alle soeben zugewiesenen Daten gedruckt. Dies können Seiten und Seiten sein. Wenn Sie es nicht sehen möchten, können Sie es stattdessen auswerten myVariable = aWholeLotOfText, 'done', und die Replik / Konsole gibt nur "Fertig" aus.

Oriel richtig weist darauf hin , angepasst , dass toString()oder get()Funktionen könnten auch dies nützlich machen.

Julian de Bhal
quelle
1
Ha, sehr schöne Idee! (Endlich eine Antwort, die die Frage tatsächlich beantwortet, im Gegensatz zu fast allen Antworten {und 3 gelöschten Antworten, für deren
Anzeige
1
Wenn der zugewiesene Wert ein Objekt ist, versucht die Konsole möglicherweise, ihn gut anzuzeigen. Dazu kann es beispielsweise Getter aufrufen, die den Status des Objekts ändern können. Die Verwendung eines Kommas kann dies verhindern.
Oriol
@Oriol - Schön! Du bist völlig richtig. Irgendwie fühlt sich das möglicherweise nützlich an, nur ein bisschen enttäuschend :)
Julian de Bhal
12

Der Komma-Operator ist nicht spezifisch für JavaScript, sondern in anderen Sprachen wie C und C ++ verfügbar . Als binärer Operator ist dies nützlich, wenn der erste Operand, der im Allgemeinen ein Ausdruck ist, die gewünschte Nebenwirkung hat, die der zweite Operand benötigt. Ein Beispiel aus Wikipedia:

i = a += 2, a + b;

Natürlich können Sie zwei verschiedene Codezeilen schreiben, aber die Verwendung von Komma ist eine weitere Option und manchmal besser lesbar.

taskinoor
quelle
1
Betrachten Sie dies als Alternative, obwohl die Definition von Gut von Mensch zu Mensch unterschiedlich sein kann. Ich kann jedoch kein Beispiel finden, in dem Sie Komma verwenden MÜSSEN. Eine andere ähnliche Sache ist ternär ?: Operator. Das kann immer durch if-else ersetzt werden, aber manchmal ?: Macht mehr lesbaren Code als if-else. Das gleiche Konzept gilt auch für Komma.
Aufgabe am
Übrigens denke ich nicht über die Verwendung von Komma in der Variablendeklaration oder die Initialisierung mehrerer Variablen in einer Schleife nach. In diesen Fällen ist Komma meistens besser.
Aufgabe am
2
das sieht verwirrend aus af ... wtf.
Timmerz
6

Ich würde Flanagan nicht zustimmen und sagen, dass Komma wirklich nützlich ist und es ermöglicht, besser lesbaren und eleganten Code zu schreiben, insbesondere wenn Sie wissen, was Sie tun:

Hier ist der sehr detaillierte Artikel zur Verwendung von Kommas:

Einige Beispiele von dort zum Beweis der Demonstration:

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

Ein Fibonacci-Generator:

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

Finden Sie das erste übergeordnete Element, analog zur jQuery- .parent()Funktion:

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">
shaman.sir
quelle
7
Ich bin mir nicht sicher, ob ich sagen würde, dass irgendetwas davon besser lesbar ist, aber es ist auf jeden Fall ziemlich schick, also +1
Chris Marisic
1
Sie brauchen das Komma in der while-Schleife im letzten Beispiel nicht, while ((el = el.parentNode) && (el.tagName != tagName.toUpperCase()))wäre in diesem Zusammenhang in Ordnung.
PitaJ
5

Ich habe keine andere praktische Verwendung gefunden, aber hier ist ein Szenario, in dem James Padolsey diese Technik für die IE-Erkennung in einer while-Schleife verwendet:

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;

}());

Diese beiden Zeilen müssen ausgeführt werden:

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

Und innerhalb des Kommaoperators werden beide ausgewertet, obwohl man sie irgendwie zu getrennten Aussagen hätte machen können.

Sarfraz
quelle
3
Dies könnte eine gewesen do- whileSchleife.
Casey Chu
4

In JavaScript kann etwas "Seltsames" ausgeführt werden, indem eine Funktion indirekt mithilfe des Kommaoperators aufgerufen wird.

Hier gibt es eine lange Beschreibung: Indirekter Funktionsaufruf in JavaScript

Mit dieser Syntax:

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

Sie können auf die globale Variable zugreifen, da sie evalbeim direkten und indirekten Aufruf anders funktioniert.

Jeremy J Starcher
quelle
4

Ich habe den Komma-Operator am nützlichsten gefunden, wenn ich solche Helfer schreibe.

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

Sie können das Komma entweder durch ein || ersetzen oder &&, aber dann müssten Sie wissen, was die Funktion zurückgibt.

Wichtiger als das ist, dass das Komma-Trennzeichen die Absicht kommuniziert - dem Code ist es egal, was der linke Operand auswertet, während die Alternativen einen anderen Grund haben können, dort zu sein. Dies erleichtert wiederum das Verständnis und die Umgestaltung. Sollte sich der Funktionsrückgabetyp jemals ändern, wäre der obige Code nicht betroffen.

Natürlich können Sie dasselbe auf andere Weise erreichen, aber nicht so prägnant. Wenn || und && haben einen Platz im allgemeinen Sprachgebrauch gefunden, ebenso der Komma-Operator.

Lambros Symeonakis
quelle
Ähnlich wie bei Ramda \ Lodash tap( ramdajs.com/docs/#tap ). Im Wesentlichen führen Sie einen Nebeneffekt aus und geben dann den Anfangswert zurück. sehr nützlich in der funktionalen Programmierung :)
Lawine1
1

Ein typischer Fall, den ich am Ende benutze, ist das optionale Parsen von Argumenten. Ich denke, es macht es sowohl lesbarer als auch prägnanter, so dass das Parsen von Argumenten den Funktionskörper nicht dominiert.

/**
 * @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();

  // ...
}
Rich Remer
quelle
Obwohl ich es selbst nicht favorisiere, ist dies das einzige Beispiel, das jemand gegeben hat, von dem ich denke, dass eine Person sagen könnte, dass es für die Lesbarkeit besser ist als die äquivalente Liste einzelner Ausdrucksaussagen, ohne dass ich denke, dass sie völlig verrückt sind.
Semikolon
1

Angenommen, Sie haben ein Array:

arr = [];

Wenn Sie pushauf dieses Array zugreifen, interessiert Sie selten der pushRückgabewert, nämlich die neue Länge des Arrays, sondern das Array selbst:

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

Mit dem Komma-Operator können wir auf das Array drücken, das Array als letzten Operanden für das Komma angeben und dann das Ergebnis - das Array selbst - für einen nachfolgenden Array-Methodenaufruf verwenden, eine Art Verkettung:

(arr.push('bar'), arr.push('baz'), arr).sort(); // [ 'bar', 'baz', 'foo' ]
Sauerstoff
quelle
-2

Ein weiterer Bereich, in dem Kommaoperatoren verwendet werden können, ist die Codeverschleierung .

Angenommen, ein Entwickler schreibt einen Code wie diesen:

var foo = 'bar';

Jetzt beschließt sie, den Code zu verschleiern. Das verwendete Tool kann den Code folgendermaßen ändern:

var Z0b=(45,87)>(195,3)?'bar':(54,65)>(1,0)?'':'baz';// Z0b == 'bar'

Demo: http://jsfiddle.net/uvDuE/

Stephan
quelle
1
@gdoron Bitte werfen Sie einen Blick auf diese Antwort stackoverflow.com/a/17903036/363573 über den Komma-Operator in C ++. Sie werden den Kommentar von James Kanze zur Verschleierung bemerken.
Stephan