Verwenden der Variablen _ (Unterstrich) mit Pfeilfunktionen in ES6 / Typescript

119

Ich bin in einem Angular-Beispiel auf dieses Konstrukt gestoßen und frage mich, warum dies gewählt wurde:

_ => console.log('Not using any parameters');

Ich verstehe, dass die Variable _ bedeutet, dass es egal ist / nicht verwendet wird, aber da es die einzige Variable ist, gibt es einen Grund, die Verwendung von _ der Verwendung von _ vorzuziehen:

() => console.log('Not using any parameters');

Sicherlich kann es sich nicht um ein Zeichen weniger handeln, das eingegeben werden muss. Die () Syntax vermittelt meiner Meinung nach die Absicht besser und ist auch typspezifischer, da ich sonst denke, dass das erste Beispiel so aussehen sollte:

(_: any) => console.log('Not using any parameters');

Falls es darauf ankommt, war dies der Kontext, in dem es verwendet wurde:

submit(query: string): void {
    this.router.navigate(['search'], { queryParams: { query: query } })
      .then(_ => this.search());
}
Halt
quelle
1
Wie können Sie sich Gedanken über die Eingabe oder Typenspezifität eines Parameters machen, der niemals verwendet wird?
3
Ich bin von Beruf ein C ++ - Entwickler, also mache ich mir wohl immer Sorgen um die Typspezifität :-).
Halt
6
Persönlich reduziert das _ => Muster die Anzahl der Klammern, um das Lesen zu erleichtern: doStuff (). Then (() => action ()) vs doStuff (). Then (_ => action ()).
Damien Golding

Antworten:

92

Der Grund, warum dieser Stil verwendet werden kann (und möglicherweise warum er hier verwendet wurde), ist, dass _ein Zeichen kürzer als ist ().

Optionale Klammern fallen in das gleiche Stilproblem wie optionale geschweifte Klammern . Dies ist größtenteils eine Frage des Geschmacks und des Codestils, aber die Ausführlichkeit wird hier aufgrund der Konsistenz bevorzugt.

Während Pfeilfunktionen einen einzelnen Parameter ohne Klammern zulassen, ist er nicht mit null, einer einzelnen destrukturierten, einer einzelnen Pause und mehreren Parametern vereinbar:

let zeroParamFn = () => { ... };
let oneParamFn = param1 => { ... };
let oneParamDestructuredArrFn = ([param1]) => { ... };
let oneParamDestructuredObjFn = ({ param1 }) => { ... };
let twoParamsFn = (param1, param2) => { ... };
let restParamsFn = (...params) => { ... };

Obwohl is declared but never usedFehler in TypeScript 2.0 ein für unterstrichene Parameter behoben wurde , _kann dies auch eine unused variable/parameterWarnung von einem Linter oder einer IDE auslösen . Dies ist ein erhebliches Argument dagegen.

_kann herkömmlicherweise für ignorierte Parameter verwendet werden (wie die andere Antwort bereits erklärt hat). Während dies als akzeptabel angesehen werden kann, kann diese Gewohnheit zu einem Konflikt mit führen_ Unterstrich / Lodash-Namespace führen. Sie sieht auch verwirrend aus, wenn mehrere Parameter ignoriert werden. Aus diesem Grund ist es vorteilhaft, unterstrichene Parameter richtig benannt zu haben (unterstützt in TS 2.0), spart auch Zeit beim Herausfinden der Funktionssignatur und warum die Parameter als ignoriert markiert werden (dies widerspricht dem Zweck des _Parameters als Verknüpfung):

let fn = (param1, _unusedParam2, param3) => { ... };

Aus den oben genannten Gründen würde ich den Codestil persönlich als _ => { ... }einen schlechten Ton betrachten, der vermieden werden sollte.

Estus Flask
quelle
1
Es ist ein Zeichen kürzer, aber für die meisten IDEs ist die Anzahl der Tastendrücke gleich hoch, da das Drücken der Taste (normalerweise mit einem Zeichen verbunden ist ). Ich persönlich bevorzuge die Verwendung pvon Parametern. Ich frage mich auch, ob es Leistungsprobleme gibt
Mojimi,
67

Die ()Syntax vermittelt die Absicht besser imho und ist auch typspezifischer

Nicht genau. ()sagt, dass die Funktion keine Argumente erwartet, keine Parameter deklariert. Die Funktionen.length ist 0.

Wenn Sie verwenden _, wird explizit angegeben, dass der Funktion ein Argument übergeben wird, dass Sie sich jedoch nicht darum kümmern. Die Funktionen.length 1, was in einigen Frameworks von Bedeutung sein kann.

Aus Sicht des Typs ist es möglicherweise genauer, dies zu tun (insbesondere, wenn Sie es nicht mit tippen, anyaber beispielsweise _: Event). Und wie Sie sagten, ist es ein Zeichen weniger zu tippen, was auch auf einigen Tastaturen leichter zu erreichen ist.

Bergi
quelle
6
Mein erster Gedanke war, dass _ nur durch Konvention deutlich macht, dass beim Versuch, die Funktion zu verstehen, keine Argumente zu berücksichtigen sind. Mit () wird deutlich, dass der Code nicht nach einer möglichen Verwendung von _ durchsucht werden muss (was gegen die Konvention verstoßen würde). Aber Sie haben meine Augen geöffnet, um auch den Wert der Dokumentation zu berücksichtigen, dass an die Funktion ein Wert übergeben wurde, der sonst nicht immer offensichtlich wäre.
Halt
Ich habe gerade festgestellt, dass mein Code voll von nicht _verwendeten ()
Pfeilfunktionsvariablen
24

Ich denke, es _ =>wird nur über verwendet, () =>weil _es in anderen Sprachen üblich ist, wo es nicht erlaubt ist, nur Parameter wie in JS wegzulassen.

_ ist in Go beliebt und wird auch in Dart verwendet, um anzuzeigen, dass ein Parameter ignoriert wird und wahrscheinlich andere, die ich nicht kenne.

Günter Zöchbauer
quelle
4
Python folgt auch dieser Konvention, denke ich.
Jaime RGP
7
Diese Verwendung von _wurde vermutlich aus funktionalen Sprachen wie ML und Haskell entlehnt, wo sie lange vor der Erfindung von Python (geschweige denn Go, Dart oder TypeScript) lag.
Ruakh
1
auch Ruby macht das ( po-ru.com/diary/rubys-magic-underscore ) und F # (und andere Sprachen, die von der ML-Familie beeinflusst werden)
Mariusz Pawelski
Scala liebt Unterstriche ( includehelp.com/scala/use-of-underscore-in-scala.aspx ). Welche weiteren Sprachen brauchten nach dem, was Scala mit anonymen Typen mit Unterstrich macht?
Sam
Ich würde vermuten, dass Scala es auch aus einer anderen Sprache übernommen hat. In Programmiersprachen gibt es kaum etwas, was es in den 70er Jahren noch nicht gab: D Meist nur neue Möglichkeiten, das Zeug zu kombinieren.
Günter Zöchbauer
11

Es ist möglich, zwischen den beiden Verwendungen zu unterscheiden, und einige Frameworks verwenden dies, um verschiedene Arten von Rückrufen darzustellen. Ich denke zum Beispiel, dass Nodes Express Framework dies verwendet, um zwischen Middleware-Typen zu unterscheiden. Beispielsweise verwenden Fehlerbehandler drei Argumente, während das Routing zwei verwendet.

Eine solche Unterscheidung kann wie im folgenden Beispiel aussehen:

const f1 = () => { } // A function taking no arguments
const f2 = _ => { }  // A function with one argument that doesn't use it

function h(ff) { 
  if (ff.length === 0) {
    console.log("No argument function - calling directly");
    ff();
  } else if (ff.length === 1) {
    console.log("Single argument function - calling with 1");
    ff(1);
  }
}

h(f1);
h(f2);

Michael Anderson
quelle
1
Dies basiert auf Bergis Antwort, aber ich dachte, das Hinzufügen eines Beispiels wäre etwas mehr Bearbeitung als ich es gerne mit einem anderen Beitrag gemacht hätte.
Michael Anderson
0

Als ich den Beitrag schrieb, hatte ich den Eindruck, dass dies _die einzige Möglichkeit war, Pfeilfunktionen ohne zu erstellen (), was mich zu der Annahme führte, dass die Verwendung _einige geringfügige Vorteile haben könnte, aber ich habe mich geirrt. @Halt hat in den Kommentaren bestätigt, dass es sich wie andere Variablen verhält, es ist kein spezielles Sprachkonstrukt.


Ich möchte noch etwas erwähnen, das ich über diese Unterstrichpfeilfunktionen beim Testen selbst festgestellt habe, das ich nirgendwo erwähnt habe. Sie können den Unterstrich in der Funktion als Parameter verwenden , obwohl dies wahrscheinlich nicht beabsichtigt ist, da er einen nicht verwendeten Parameter darstellen soll. Aus Gründen der Klarheit würde ich es nicht wirklich empfehlen, es so zu verwenden. Aber es kann nützlich sein, Dinge wie Codegolf zu kennen , Herausforderungen, bei denen Sie den kürzesten Code schreiben (es stellt sich heraus, dass Sie einfach jedes Zeichen ohne verwenden können ()). Ich könnte mir einige reale Anwendungsfälle vorstellen, in denen Bibliotheken dies verwenden und Sie es verwenden müssen, auch wenn sie diese Funktionalität nicht beabsichtigt haben.

Beispiel:

// simple number doubling function
f = _=> {
    _ = _ * 2;
    return _;
}

console.log(f(2)); // returns 4
console.log(f(10)); // returns 20

Getestet mit der Chrome-Konsole, Version 76.0.3809.132 (Official Build) (64-Bit)

Matsyir
quelle
1
Der Unterstrich '_' ist ein legaler Variablenname und kein spezielles Sprachkonstrukt, das nur durch Konvention eine besondere Bedeutung erhält. Linter-Warnungen vor nicht verwendeten Parametern können mithilfe des Unterstrichpräfixes stummgeschaltet werden. Ich denke, _ an sich ist nur der kürzeste Weg, um unbenutzt zu sagen.
Halt
@Halt Danke für die Klarstellung, sicher gut zu wissen. Ich wusste eigentlich nicht, dass man Pfeilfunktionen ohne die erstellen kann, ()bevor ich diesen Beitrag verfasst habe. Ich dachte, dies wäre _der einzige Weg, weshalb ich mich entschied, darauf hinzuweisen. In diesem Sinne stellt sich heraus, dass es auch für das Golfen nichts Besonderes ist, da man einfach einen normalen Charakter verwenden kann. Besser einfach zum Befolgen von Konventionen verwendet, wie Sie sagten.
Matsyir