466 Stimmen

Gibt es eine Möglichkeit, benannte Parameter in einem Funktionsaufruf in JavaScript anzugeben?

Ich finde die Funktion der benannten 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 dies:

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 verfolgt. Gibt es einen anderen Weg?

Ich habe kein Problem damit, eine beliebige Bibliothek dafür zu verwenden.

3voto

Dmitri Zaitsev Punkte 12685

Aufruf der Funktion f mit benannten Parametern, die als Objekt übergeben werden

o = {height: 1, width: 5, ...}

nennt im Grunde seine Zusammensetzung f(...g(o)) wo ich die Spread-Syntax verwende und g ist eine "verbindliche" Karte, die die Objektwerte mit ihren Parameterpositionen verbindet.

Die Bindungskarte ist genau die fehlende Zutat, die durch das Array ihrer Schlüssel dargestellt werden kann:

// map 'height' to the first and 'width' to the second param
binding = ['height', 'width']

// take binding and arg object and return aray of args
withNamed = (bnd, o) => bnd.map(param => o[param])

// call f with named args via binding
f(...withNamed(binding, {hight: 1, width: 5}))

Beachten Sie die drei entkoppelte Bestandteile: die Funktion, das Objekt mit benannten Argumenten und die Bindung. Diese Entkopplung ermöglicht eine große Flexibilität bei der Verwendung dieses Konstrukts, wobei die Bindung in der Funktionsdefinition beliebig angepasst und beim Funktionsaufruf beliebig erweitert werden kann.

Sie können zum Beispiel Folgendes abkürzen height y width comme h y w innerhalb Ihrer Funktionsdefinition, um sie kürzer und übersichtlicher zu gestalten, während Sie sie aus Gründen der Klarheit weiterhin mit vollständigen Namen aufrufen möchten:

// use short params
f = (h, w) => ...

// modify f to be called with named args
ff = o => f(...withNamed(['height', 'width'], o))

// now call with real more descriptive names
ff({height: 1, width: 5})

Diese Flexibilität ist auch für die funktionale Programmierung nützlich, wo Funktionen beliebig transformiert werden können, ohne dass ihre ursprünglichen Parameternamen verloren gehen.

3voto

Schalton Punkte 2465

Dies ist zugegebenermaßen Pseudocode, aber ich glaube, es wird funktionieren (ich weiß, dass es in TypeScript funktioniert; ich übernehme es für JavaScript).

// Target Function
const myFunc = (a=1,b=2,c=3) => {a+b+c}

// Goal usage:
myFunc(a=5, b=6) // 14
myFunc(c=0) // 3

// Set your defaults
const myFuncDefaults = {a:1, b:2, c:3};

// Override them with passed parameters
const myFuncParams = (params) => { return Object.assign(myFuncDefaults, params)}

// Use the overloaded dict as the input
const myFunc2 = (params) => {
  let {a, b, c} = myFuncParams(params);
  return myFunc(a, b, c)
}

// Usage:
myFunc({a:5, b:6}) // 14
myFunc({c:0}) // 3

// Written more succinctly:
const myFunc = (params) => {
  let {a,b,c} = Object.assign({a:1, b:2, c:3}, params)
  return a + b + c
}

Was auch immer es wert ist, TypeScript macht diese Art von nett mit Hinting:

interface IParams {
  a: number;
  b: number;
  c: number;
}

const myFunc = (params: Partial<IParams>): number => {
  const default: IParams = {a:1, b:2, c:3};
  let {a, b, c} = Object.assign(default, params)
  return a + b + c
}

2voto

Allen Ellison Punkte 67

Es gibt einen anderen Weg. Wenn Sie ein Objekt per Verweis übergeben, werden die Eigenschaften dieses Objekts im lokalen Bereich der Funktion angezeigt. Ich weiß, dass dies für Safari funktioniert (andere Browser habe ich 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 glaube, dass dies einen funktionalen Wert über die Technik, die Sie bereits verwenden, bietet, ist es ein wenig sauberer semantisch. Und es erfordert immer noch die Übergabe einer Objektreferenz oder eines Objektliteral.

function sum({ a:a, b:b}) {
    console.log(a+'+'+b);
    if(a==undefined) a=0;
    if(b==undefined) b=0;
    return (a+b);
}

// will work (returns 9 and 3 respectively)
console.log(sum({a:4,b:5}));
console.log(sum({a:3}));

// will not work (returns 0)
console.log(sum(4,5));
console.log(sum(4));

1voto

jgran Punkte 939

NB. Meine Antwort von 2016 ist nicht korrekt und irreführend, wie in den Kommentaren erwähnt.

Beim Ausprobieren von 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 sind fast umgesetzt, aber diese Reihenfolge hat immer noch Vorrang. Ich kann nicht herausfinden, was in der ECMA-Norm steht.

>function f(a=1, b=2){ console.log(`a=${a} + b=${b} = ${a+b}`) }

> f()
a=1 + b=2 = 3
> f(a=5)
a=5 + b=2 = 7
> f(a=7, b=10)
a=7 + b=10 = 17

Aber Ordnung muss sein!! Ist das das Standardverhalten?

> f(b=10)
a=10 + b=2 = 12

1voto

Vince Spicer Punkte 3855

Da ich von Python komme, stört mich das. Ich habe einen einfachen Wrapper/Proxy für Node geschrieben, der sowohl positionale als auch Keyword-Objekte akzeptiert.

https://github.com/vinces1979/node-def/blob/master/README.md

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X