Ich finde die Funktion für benannte Parameter in C # in einigen Fällen sehr nützlich.
calculateBMI(70, height: 175);
Was kann ich verwenden, wenn ich dies in JavaScript möchte?
Was ich nicht will ist folgendes:
myFunction({ param1: 70, param2: 175 });
function myFunction(params){
// Check if params is an object
// Check if the parameters I need are non-null
// Blah blah
}
Diesen Ansatz habe ich bereits verwendet. Gibt es eine andere Art und Weise?
Ich bin in Ordnung, wenn ich dazu eine Bibliothek benutze.
javascript
function
optional-parameters
named-parameters
Robin Maben
quelle
quelle
Function
in Javascript vorhandene kann.Function
in Javascript vorhandene kann diecalculateBMI(70, /*height:*/ 175);
, (2) ein Objekt bereitstellencalculateBMI(70, {height: 175})
oder (3) eine Konstante verwendenconst height = 175; calculateBMI(70, height);
.Antworten:
ES2015 und höher
In ES2015 kann die Parameterdestrukturierung verwendet werden, um benannte Parameter zu simulieren. Der Aufrufer müsste ein Objekt übergeben, aber Sie können alle Überprüfungen innerhalb der Funktion vermeiden, wenn Sie auch Standardparameter verwenden:
ES5
Es gibt eine Möglichkeit, dem, was Sie wollen, nahe zu kommen, aber sie basiert auf der Ausgabe von
Function.prototype.toString
[ES5] , die in gewissem Maße von der Implementierung abhängt, sodass sie möglicherweise nicht browserübergreifend kompatibel ist.Die Idee ist, die Parameternamen aus der Zeichenfolgendarstellung der Funktion zu analysieren, damit Sie die Eigenschaften eines Objekts dem entsprechenden Parameter zuordnen können.
Ein Funktionsaufruf könnte dann so aussehen
wo
a
undb
sind Positionsargumente und das letzte Argument ist ein Objekt mit benannten Argumenten.Beispielsweise:
Welche würden Sie verwenden als:
DEMO
Dieser Ansatz weist einige Nachteile auf (Sie wurden gewarnt!):
undefined
(der sich davon unterscheidet, überhaupt keinen Wert zu haben). Das heißt, Sie können nichtarguments.length
testen, wie viele Argumente übergeben wurden.Anstatt dass eine Funktion den Wrapper erstellt, können Sie auch eine Funktion verwenden, die eine Funktion und verschiedene Werte als Argumente akzeptiert, z
oder sogar verlängern,
Function.prototype
damit Sie tun können:quelle
Object.defineProperty
und Satzenumerable
zufalse
). Man sollte immer vorsichtig sein, wenn man native Objekte erweitert. Der ganze Ansatz fühlt sich ein bisschen hackig an, daher würde ich nicht erwarten, dass er jetzt und für immer funktioniert;)undefined
vs "no value" kann hinzugefügt werden, dass genau so die Standardwerte von JS-Funktionen funktionieren -undefined
als fehlender Wert behandelt.Nein - der Objektansatz ist die Antwort von JavaScript darauf. Dies ist kein Problem, vorausgesetzt, Ihre Funktion erwartet ein Objekt und keine separaten Parameter.
quelle
Dieses Problem ist seit einiger Zeit ein Liebling von mir. Ich bin ein erfahrener Programmierer mit vielen Sprachen. Eine meiner Lieblingssprachen, die ich gerne benutzt habe, ist Python. Python unterstützt benannte Parameter ohne Tricks .... Seit ich vor einiger Zeit mit Python angefangen habe, wurde alles einfacher. Ich glaube, dass jede Sprache benannte Parameter unterstützen sollte, aber das ist einfach nicht der Fall.
Viele Leute sagen, sie sollen nur den Trick "Objekt übergeben" verwenden, damit Sie Parameter benannt haben.
Und das funktioniert großartig, außer ... wenn es um die meisten IDEs geht, verlassen sich viele von uns Entwicklern auf Typ- / Argument-Hinweise in unserer IDE. Ich persönlich benutze PHP Storm (zusammen mit anderen JetBrains-IDEs wie PyCharm für Python und AppCode für Objective C)
Das größte Problem bei der Verwendung des Tricks "Objekt übergeben" besteht darin, dass die IDE beim Aufrufen der Funktion einen einzigen Typhinweis gibt und das war's ... Wie sollen wir wissen, welche Parameter und Typen in die Funktion aufgenommen werden sollen? arg1 Objekt?
Also ... der Trick "Objekt übergeben" funktioniert bei mir nicht ... Es verursacht tatsächlich mehr Kopfschmerzen, wenn ich mir den Docblock jeder Funktion ansehen muss, bevor ich weiß, welche Parameter die Funktion erwartet ... Sicher, es ist großartig für Wenn Sie vorhandenen Code beibehalten, es aber schrecklich ist, neuen Code zu schreiben.
Nun, dies ist die Technik, die ich verwende ... Nun, es kann einige Probleme geben, und einige Entwickler sagen mir vielleicht, dass ich es falsch mache, und ich bin offen für diese Dinge ... Ich bin immer bereit, nach besseren Möglichkeiten zu suchen, um eine Aufgabe zu erfüllen ... Wenn es also ein Problem mit dieser Technik gibt, sind Kommentare willkommen.
Auf diese Weise habe ich das Beste aus beiden Welten ... neuer Code ist einfach zu schreiben, da meine IDE mir alle richtigen Argumentationshinweise gibt ... Und während ich später den Code pflege, kann ich auf einen Blick nicht nur den sehen Wert, der an die Funktion übergeben wird, aber auch der Name des Arguments. Der einzige Aufwand, den ich sehe, besteht darin, Ihre Argumentnamen als lokale Variablen zu deklarieren, um zu verhindern, dass der globale Namespace verschmutzt wird. Sicher, es ist ein bisschen mehr Tipparbeit, aber trivial im Vergleich zu der Zeit, die benötigt wird, um Docblocks nachzuschlagen, während neuer Code geschrieben oder vorhandener Code beibehalten wird.
quelle
myFunc(/*arg1*/ 'Param1', /*arg2*/ 'Param2');
ist besser alsmyFunc(arg1='Param1', arg2='Param2');
, weil das keine Chance hat, den Leser zu täuschen, als irgendwelche tatsächlich genannten Argumente passierenWenn Sie klarstellen möchten, um welche Parameter es sich handelt, anstatt nur aufzurufen
Warum nicht folgendes tun?
Sicher, es ist eine zusätzliche Codezeile, aber sie gewinnt an Lesbarkeit.
quelle
someFunction(height: 115);
, aber wenn Sie schreiben, stellensomeFunction(height);
Sie tatsächlich die Breite ein.someFunction(width = 70, height = 115);
. Die Variablen werden im generierten JavaScript-Code am oberen Rand des aktuellen Bereichs deklariert.Eine andere Möglichkeit wäre, Attribute eines geeigneten Objekts zu verwenden, z. B. wie folgt:
Natürlich ist es für dieses erfundene Beispiel etwas bedeutungslos. Aber in Fällen, in denen die Funktion aussieht
es könnte nützlicher sein. Es könnte auch mit der Idee "parameterfy" kombiniert werden, ein solches Objekt auf generische Weise aus einer vorhandenen Funktion zu erstellen. Das heißt, für jeden Parameter wird ein Element erstellt, das zu einer teilweise ausgewerteten Version der Funktion ausgewertet werden kann.
Diese Idee hängt natürlich mit Schönfinkeling aka Currying zusammen.
quelle
Es geht auch anders. Wenn Sie ein Objekt als Referenz übergeben, werden die Eigenschaften dieses Objekts im lokalen Bereich der Funktion angezeigt. Ich weiß, dass dies für Safari funktioniert (habe andere Browser nicht überprüft) und ich weiß nicht, ob diese Funktion einen Namen hat, aber das folgende Beispiel veranschaulicht ihre Verwendung.
Obwohl ich in der Praxis nicht denke, dass dies einen funktionalen Wert bietet, der über die bereits verwendete Technik hinausgeht, ist es semantisch etwas sauberer. Außerdem muss eine Objektreferenz oder ein Objektliteral übergeben werden.
quelle
Beim Versuch mit Node-6.4.0 (process.versions.v8 = '5.0.71.60') und Node Chakracore-v7.0.0-pre8 und dann Chrome-52 (V8 = 5.2.361.49) habe ich festgestellt, dass benannte Parameter fast sind implementiert, aber diese Reihenfolge hat immer noch Vorrang. Ich kann nicht finden, was der ECMA-Standard sagt.
Aber Bestellung ist erforderlich !! Ist es das Standardverhalten?
quelle
b=10
Ausdrucks ist10
, und das wird an die Funktion übergeben.f(bla=10)
würde auch funktionieren (es weist der Variablen 10 zubla
und übergibt den Wert anschließend an die Funktion).a
undb
Variablen im globalen Bereich als Nebeneffekt.Aufruffunktion
f
mit benannten Parametern als Objekt übergebennennt im Grunde seine Zusammensetzung,
f(...g(o))
wo ich die Spread-Syntax verwende undg
ist eine "bindende" Map, die die Objektwerte mit ihren Parameterpositionen verbindet.Die Bindungskarte ist genau die fehlende Zutat, die durch das Array ihrer Schlüssel dargestellt werden kann:
Beachten Sie die drei entkoppelten Bestandteile: die Funktion, das Objekt mit den benannten Argumenten und die Bindung. Diese Entkopplung ermöglicht eine große Flexibilität bei der Verwendung dieses Konstrukts, bei dem die Bindung in der Funktionsdefinition beliebig angepasst und zum Zeitpunkt des Funktionsaufrufs beliebig erweitert werden kann.
Zum Beispiel möchten Sie möglicherweise abkürzen
height
undwidth
alsh
undw
innerhalb der Definition Ihrer Funktion, um sie kürzer und sauberer zu machen, während Sie sie aus Gründen der Klarheit immer noch mit vollständigen Namen aufrufen möchten:Diese Flexibilität ist auch für die funktionale Programmierung nützlicher, bei der Funktionen beliebig transformiert werden können, wobei ihre ursprünglichen Parameternamen verloren gehen.
quelle
Als ich aus Python kam, nervte mich das. Ich habe einen einfachen Wrapper / Proxy für Knoten geschrieben, der sowohl Positions- als auch Schlüsselwortobjekte akzeptiert.
https://github.com/vinces1979/node-def/blob/master/README.md
quelle
f(x, opt)
Woopt
befindet sich ein Objekt ? Ob es hilft, Fehler zu vermeiden oder zu verursachen (z. B. durch Rechtschreibfehler und den Schmerz, sich Schlüsselwortnamen zu merken), bleibt eine Frage.kwargs
dict eins nach dem anderen und schließlich eine erhöhen ,TypeError
wenn unbekannte Schlüssel gelassen werden). Ihref(x, opt)
Lösung ermöglicht es derf
Funktion, etwas wie in Python 2 zu tun, aber Sie müssten alle Standardwerte selbst behandeln.f(x, opt)
es bereits funktioniert, obwohl ich nicht sehe, wie dies zur Beantwortung der Frage beiträgt, wo z. B. Sie beides tun möchtenrequest(url)
undrequest({url: url})
dies nicht möglich wäre , wenn Sieurl
nur einen Schlüsselwortparameter erstellen .Im Gegensatz zu dem, was allgemein angenommen wird, können benannte Parameter in Standard-JavaScript der alten Schule (nur für boolesche Parameter) mithilfe einer einfachen, übersichtlichen Codierungskonvention implementiert werden, wie unten gezeigt.
Vorsichtsmaßnahmen:
Die Reihenfolge der Argumente muss beibehalten werden - das Muster ist jedoch weiterhin nützlich, da deutlich wird, welches tatsächliche Argument für welchen formalen Parameter bestimmt ist, ohne nach der Funktionssignatur suchen oder eine IDE verwenden zu müssen.
Dies funktioniert nur für Boolesche Werte. Ich bin jedoch sicher, dass ein ähnliches Muster für andere Typen unter Verwendung der einzigartigen Typ-Zwangssemantik von JavaScript entwickelt werden könnte.
quelle
height
unabhängig von der Reihenfolge der Parameter einen Namen zu vergeben.