2012-06-23 12 views
5

Für die Benutzerfreundlichkeit habe ich eine Funktion, die zuerst ein optionales Argument vor dem erforderlichen Argument erhält. Zum Beispiel:Optionales Argument zuerst in JavaScript

ns.myFunction('optional arg', function(){ 
    //the required callback 
}); 

ich dies zu tun, anstatt Sie folgendermaßen vorgehen, da der Rückruf Körper lang sein könnte, und der Benutzer könnte vergessen, die standardmäßig auf die optionalen Argumente außer Kraft zu setzen:

ns.myFunction(function(){ 
    //the required callback 
}, 'optional arg'); 

Aktuell ich tue dies zu überprüfen:

function myFunction(first, second) { 

    //if second is undefined and first is a function 
    if (typeof second === 'undefined' && typeof first === 'function') { 
     second = first; 
    } 
} 

Fragen

  • Ist das der richtige Weg?
  • Wie würde ich es tun, damit es skaliert, vor allem, wenn N optionale Argumente vor dem erforderlichen Argument waren?
+1

Warum würden Sie die optionalen Argumente nicht am * Ende * der Argumentliste platzieren? Das ist in JavaScript aufgrund der Semantik von '.bind()' nützlicher. Die "stabileren" Argumente sollten an erster Stelle stehen, wobei die Wahrscheinlichkeit größer ist, dass sie am Ende variieren oder fehlen. – Pointy

+0

@Pointy Ich bin nur neugierig, wie Bibliotheken es so machen und ob es eine richtige Methode gibt. Zum Beispiel hat jQuery 'extend' ein Deepcopy-Flag, das optional in der allerersten Argumentliste liegt. – Joseph

+1

Wie wäre es mit 'Argumente [..]'? Würde ich nicht durch das Array iterieren und bei der ersten 'typeof arguments [i] === 'function'-Hilfe stoppen? – SuperSaiyan

Antwort

1

Es ist nicht notwendig, einen der Parameter zu benennen. Sie können einfach sagen:

if (arguments.length < 2) // There are no optional parameters 

Und abrufen Sie jeden Parameter über Argumente [i]. Die Funktion befindet sich in Argumenten [Argumente.Länge - 1].

Auf einer kleinen Notiz, kehrt der typeof-Operator immer einen String, so == kann nicht die rechts Weg Dies ist statt ===

3

verwendet werden, da optionale Parameter durch Konvention sind immer auf der platziert Ende. Und Sie sehen einen Grund, warum: Es ist viel einfacher, mit ihnen umzugehen. Wenn er Länge anonymer Funktion Ihr Anliegen ist, sollten Kunden Ihrer API-Funktion Verweise oder Variablen verwenden:

function callback1() { //... 

var callback2 = function() {//... 

myFunction(callbackX, optional); 

Das Problem mit this entkommen kann mit bind() gelöst werden.

Wenn Sie wirklich den Pfad mehrerer optionaler Parameter und Callback am Ende gehen wollen, kann ich zwei Möglichkeiten finden: arguments Objekt oder alle optionalen Argumente in einem options Objekte umhüllen.

Mit arguments können Sie schreiben:

var lastOptionalIndex = arguments.length - 2; 
var callback = arguments[lastOptionalIndex + 1]; //required callback is always last 
var optionalFirst = lastOptionalIndex >=0? arguments[0] : undefined; 
var optionalSecond = lastOptionalIndex >=1? arguments[1] : undefined; 
//... 

Sehen Sie, wie hässlich es ist im Vergleich zu:

function myFunction(callback, firstOptional, secondOptional //... 

Mit options Wrapper-Objekt zwei Argumente immer haben:

function myFunction(options, callback); 

Wo options ist nur ein Objekt:

{ 
    firstOptional: 1, 
    secondOptional: 'foo' 
    //... 
} 
+1

Ja, die Verwendung eines Optionsobjekt-Parameters entweder vor oder nach der Callback-Funktion ist ein guter Weg. Und es ist viel einfacher, Standardwerte mit der extend-Methode zuzuweisen. –

0

Wenn Sie wirklich erste mehrere optionale Parameter übergeben wollen, können Sie es wie folgt tun:

function myFunction() { 
    alert("optional:"); 
    for(var i=0; i<arguments.length-1) alert(arguments[i]); 
    alert("function: "+ arguments[arguments.length-1]); 
} 

Aber es ist ziemlich hässlich.Ich denke du solltest einfach das optionale Zeug am Ende hinstellen.

function myFunction(){ 
    arguments = __({first: [String], second: Function}) 

    // and now on, you can access your arguments by 
    // arguments.first and arguments.second 
} 

Ein sehr ähnliches Beispiel finden Sie unter: ArgueJS' first example:

2

Es kann easilly mit ArgueJS erfolgen. Beachten Sie, dass nur der Parameter in der Mitte erforderlich:

function range(){ 
    arguments = __({start: [Number, 0], stop: Number, step: [Number, 1]}) 

    for(var i = arguments.start; i < arguments.stop; i += arguments.step) 
    console.log(i); 
} 

repl:

>>> range(3) 
0 
1 
2 
>>> range(3, 5) 
3 
4 
>>> range(0, 5, 2) 
0 
2 
4 
0

ArgueJS:

function range(){ 
    arguments = __({start: [Number, 0], stop: Number, step: [Number, 1]}); 
    for(var i = arguments.start; i < arguments.stop; i += arguments.step) 
    console.log(i); 
} 

Werden Sie noch schöner mit ES6:

function range(){ 
    {start, stop, step} = __({start: [Number, 0], stop: Number, step: [Number, 1]}) 
    for(var i = start; i < stop; i += step) 
    console.log(i); 
} 

Or KaffeeScript:

range = -> 
    {start, stop, step} = __ {start: [Number, 0], stop: Number, step: [Number, 1]} 
    console.log i for i in [start...stop] by step 
Verwandte Themen