2015-06-16 15 views
10

Ich bin sicher, dass dies relativ einfach ist und dass ich etwas offensichtlich vermisse. Ich lese über Mozilla's tutorials auf ES6 und ihre chapter on destructuring enthält folgende Muster:Funktion Parameterdefinitionen in ES6

FUNCTION Parameter-Definitionen

Als Entwickler können wir oft durch die Annahme eines einzelnes Objekt mit mehreren ergonomischere APIs belichten Eigenschaften als Parameter anstelle von zwingen unsere API-Consumer auf die Reihenfolge vieler einzelner Parameter erinnern. Wir können Destrukturierung verwenden, um zu vermeiden diese einzelne Objektparameter zu wiederholen, wenn wir eine seiner Eigenschaften verweisen möchten:

function removeBreakpoint({ url, line, column }) { 
    // ... 
} 

Dies ist eine vereinfachte Ausschnitt aus der realen Welt Code aus dem Firefox DevTools JavaScript-Debugger (die auch umgesetzt wird in JavaScript-yo Dawg). Wir haben dieses Muster besonders erfreulich gefunden.

Was ich nicht verstehe, ist, wie sich dies auf die Destrukturierung bezieht. Ist die Idee, dass Sie die Fähigkeit erlauben, ein Objekt in diese Funktion zu übergeben, die in beliebiger Reihenfolge sein kann, solange es alle Elemente enthält, d. H. { line: 10, column: 20, url: 'localhost' }?

Wenn ja, was ist der Vorteil gegenüber so etwas wie

function removeBreakpoint(params) { 
    // ... 
} 

wo params ist ein Objekt mit url, line und column? Ist die Idee nur, dass Sie Javascript zwingen, die Parameter einer Funktion zu validieren, wenn sie in einem destrukturierten Kontext verwendet werden, indem Sie sie explizit definieren?

+1

"ein Objekt ... das in beliebiger Reihenfolge sein kann, solange es alle Objekte enthält" Objekte haben keinen Auftrag und Sie müssen nicht alle Objekte haben. Keine Validierung oder Verarbeitung erfolgt. Der Vorteil ist, dass Sie nicht die Funktion body reference 'params.url',' params.line', 'params.column' haben, sondern direkt auf' url', 'line' und' column' verweisen können. – Barney

+0

Sinn für mich. – fox

+1

@Barney: Objekteigenschaften haben keine Reihenfolge in ** ES5 **. [Sie ** tun ** in ES6] (https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys). –

Antwort

15

Was ich nicht verstehe, ist, wie sich dies auf die Destrukturierung bezieht.

Innerhalb removeBreakpoint, können Sie url, line und column direkt. Die Destrukturierung geschieht, wenn removeBreakpoint mit einem Optionsobjekt aufgerufen wird; Die übereinstimmenden Eigenschaften dieses Objekts werden in einzelne Argumente destrukturiert.

Ist die Idee, dass Sie die Fähigkeit erlauben, ein Objekt in diese Funktion zu übergeben, die in beliebiger Reihenfolge sein kann, solange es alle Elemente enthält, dh {Zeile: 10, Spalte: 20, URL: 'localhost' }?

Ja, aber es muss nicht alle Elemente enthalten; Wenn dies nicht der Fall ist, lautet das Argument undefined (es sei denn, ein Standardwert ist angegeben), da das Argument von einer Objekteigenschaft initialisiert wird, die nicht existiert.

Einfaches Beispiel demonstriert die Destrukturierung (Live Copy with ES5 translation auf Babel ‚s REPL):

"use strict"; 
function removeBreakpoint({ url, line, column }) { 
    console.log("removeBreakpoint:"); 
    console.log("url: " + url); 
    console.log("line: " + line); 
    console.log("column: " + column); 
} 
removeBreakpoint({ 
    url: "the url", 
    line: "the line", 
    column: "the column" 
}); 
removeBreakpoint({ 
    url: "the url", 
    line: "the line" 
}); 

Ausgang:

 
removeBreakpoint: 
url: the url 
line: the line 
column: the column 
removeBreakpoint: 
url: the url 
line: the line 
column: undefined 

Wenn ja, was ist der Vorteil gegenüber so etwas wie

function removeBreakpoint(params) { 
    // ... 
} 

wo params ein Objekt mit URL, Zeile und Spalte ist?

Syntaktischer Zucker. Die neue Syntax zum Akzeptieren von Optionsobjekten ist prägnanter und deklarativer und automatisiert ein allgemeines Muster. Dies ist besonders offensichtlich, wenn Sie es mit Standardwerten kombinieren (Live Copy):

"use strict"; 
function removeBreakpoint(
    {        // <= { starts destructuring arg 
     url = "url default",  // <= Default for `url` 
     line = "line default",  // <= ...for `line` 
     column = "column default" // <= ...for `column` 
    }        // <= } ends destructuring arg 
    = {}       // <= Default for the options object iself 
) {         // (see notes after the code block) 
    console.log("removeBreakpoint:"); 
    console.log(url); 
    console.log(line); 
    console.log(column); 
} 
removeBreakpoint({ 
    url: "the url", 
    line: "the line", 
    column: "the column" 
}); 
removeBreakpoint({ 
    url: "the url", 
    line: "the line" 
}); 
removeBreakpoint(); 

Ausgang:

 
removeBreakpoint: 
the url 
the line 
the column 
removeBreakpoint: 
the url 
the line 
column default 
removeBreakpoint: 
url default 
line default 
column default 

In den oben, auch die Optionen Objekt selbst optional ist, weshalb die letzte Anruf Werke :

removeBreakpoint(); 

Wenn wir einen Standard für die Optionen selbst Objekt nicht gegeben hätte, hätte dieser Anruf fehlgeschlagen wäre, weil wir die Eigenschaft lesen würde versuchen url von undefined. Manchmal möchten Sie das, und so lassen Sie die Gesamtoption aus. Andere Zeiten nicht.


Randbemerkung: Die Fähigkeit, Objektteile der Optionen auf dem Standard und auch getrennt, die gesamten Optionen Objekt führt zu einer interessanten Situation, wo Sie unterschiedliche Standardwerte je nachdem, ob ein Options Objekt gegeben haben, aber keine spezifische Möglichkeit haben, gegen keine Optionen auf alle Objekt gegeben wird, alle deklarativ gemacht: Live Copy

"use strict"; 
function test(
    num, 
    { 
     foo = "foo default", 
     bar = "options given without bar" 
    } = {bar: "options not given at all"} 
) { 
    console.log(num + ": foo = " + foo + ", bar = " + bar); 
} 
test(1, {foo: "foo value", bar: "options given with bar"}); 
test(2, {bar: "options given with bar"}); 
test(3, {}); 
test(4); 

Ausgang:

 
1: foo = foo value, bar = options given with bar 
2: foo = foo default, bar = options given with bar 
3: foo = foo default, bar = options given without bar 
4: foo = foo default, bar = options not given at all