864 Stimmen

Gibt es eine bessere Möglichkeit, optionale Funktionsparameter in JavaScript zu verwenden?

Ich habe optionale Parameter in JavaScript immer wie folgt behandelt:

function myFunc(requiredArg, optionalArg){
  optionalArg = optionalArg || 'defaultValue';

  // Do stuff
}

Gibt es einen besseren Weg, dies zu tun?

Gibt es Fälle, in denen die Verwendung von || wie das scheitern wird?

10 Stimmen

6 Stimmen

Das ist interessant. Übergabe Argumente als ein assoziatives Array scheint ein guter Weg, um mehr als ein paar Argumente zu behandeln.

1 Stimmen

Das ist genau das, was ich in den meisten Fällen tue. Meine Funktionen mit mehr als einem Argument erwarten ein Objektliteral.

6voto

Yann Bertrand Punkte 3063

Mit ES2015/ES6 können Sie die folgenden Vorteile nutzen Object.assign die ersetzen können $.extend() o _.defaults()

function myFunc(requiredArg, options = {}) {
  const defaults = {
    message: 'Hello',
    color: 'red',
    importance: 1
  };

  const settings = Object.assign({}, defaults, options);

  // do stuff
}

Sie können auch Standardargumente wie diese verwenden

function myFunc(requiredArg, { message: 'Hello', color: 'red', importance: 1 } = {}) {
  // do stuff
}

3voto

roo2 Punkte 5799

Wenn Sie die Unterstrich Bibliothek (das sollten Sie, es ist eine großartige Bibliothek):

_.defaults(optionalArg, 'defaultValue');

2voto

slartibartfast Punkte 522

Der Test für undefiniert ist unnötig und ist nicht so robust, wie es sein könnte, weil, wie user568458 darauf hingewiesen, die bereitgestellte Lösung fehlschlägt, wenn null oder false übergeben wird. Benutzer Ihrer API könnten denken, dass false oder null die Methode zwingen würde, diesen Parameter zu vermeiden.

function PaulDixonSolution(required, optionalArg){
   optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
   console.log(optionalArg);
};
PaulDixonSolution("required");
PaulDixonSolution("required", "provided");
PaulDixonSolution("required", null);
PaulDixonSolution("required", false);

Das Ergebnis ist:

defaultValue
provided
null
false

Die letzten beiden sind potenziell schlecht. Versuchen Sie es stattdessen:

function bulletproof(required, optionalArg){
   optionalArg = optionalArg ? optionalArg : "defaultValue";;
   console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);

Daraus ergibt sich:

defaultValue
provided
defaultValue
defaultValue

Das einzige Szenario, in dem dies nicht optimal ist, ist, wenn Sie tatsächlich optionale Parameter haben, die als Boolesche Werte oder absichtlich als Null definiert sind.

2voto

Arman Punkte 4746

Ich weiß nicht, warum die Antwort von @Paul heruntergestuft wird, aber die Validierung gegen null ist eine gute Wahl. Vielleicht macht ein positiveres Beispiel mehr Sinn:

In JavaScript ist ein fehlender Parameter wie eine deklarierte Variable, die nicht initialisiert ist (nur var a1; ). Der Gleichheitsoperator wandelt undefinierte Werte in Null um, so dass dies sowohl mit Werttypen als auch mit Objekten funktioniert, und so behandelt CoffeeScript optionale Parameter.

function overLoad(p1){
    alert(p1 == null); // Caution, don't use the strict comparison: === won't work.
    alert(typeof p1 === 'undefined');
}

overLoad(); // true, true
overLoad(undefined); // true, true. Yes, undefined is treated as null for equality operator.
overLoad(10); // false, false

function overLoad(p1){
    if (p1 == null) p1 = 'default value goes here...';
    //...
}

Allerdings gibt es Bedenken, dass für die beste Semantik ist typeof variable === 'undefined' ist etwas besser. Ich werde dies nicht verteidigen, da es eine Frage der zugrunde liegenden API ist, wie eine Funktion implementiert wird; es sollte den API-Nutzer nicht interessieren.

Ich sollte noch hinzufügen, dass dies die einzige Möglichkeit ist, um sicherzustellen, dass kein Argument übersehen wurde, indem man die in Operator, der leider nicht mit den Parameternamen funktioniert, so dass man einen Index der arguments .

function foo(a, b) {
    // Both a and b will evaluate to undefined when used in an expression
    alert(a); // undefined
    alert(b); // undefined

    alert("0" in arguments); // true
    alert("1" in arguments); // false
}

foo (undefined);

2voto

JDC Punkte 1329

Ich habe einige der hier genannten Optionen ausprobiert und ihre Leistung getestet. Im Moment scheint der Logicor am schnellsten zu sein. Allerdings kann sich dies im Laufe der Zeit ändern (verschiedene JavaScript-Engine-Versionen).

Dies sind meine Ergebnisse (Microsoft Edge 20.10240.16384.0):

Function executed            Operations/sec     Statistics
TypeofFunction('test');          92,169,505     ±1.55%   9% slower
SwitchFuntion('test');            2,904,685     ±2.91%  97% slower
ObjectFunction({param1: 'test'});   924,753     ±1.71%  99% slower
LogicalOrFunction('test');      101,205,173     ±0.92%     fastest
TypeofFunction2('test');         35,636,836     ±0.59%  65% slower

Dieser Leistungstest kann leicht nachgestellt werden: http://jsperf.com/optional-parameters-typeof-vs-switch/2

Dies ist der Code des Tests:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        function TypeofFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 = (typeof optParam1 === "undefined") ? "Some default" : optParam1;
            optParam2 = (typeof optParam2 === "undefined") ? "Another default" : optParam2;
            optParam3 = (typeof optParam3 === "undefined") ? "Some other default" : optParam3;
        }

        function TypeofFunction2(param1, optParam1, optParam2, optParam3) {
            optParam1 = defaultValue(optParam1, "Some default");
            optParam2 = defaultValue(optParam2, "Another default");
            optParam3 = defaultValue(optParam3, "Some other default");
        }

        function defaultValue(variable, defaultValue) {
            return (typeof variable !== 'undefined') ? (variable) : (defaultValue);
        }

        function SwitchFuntion(param1, optParam1, optParam2, optParam3) {
            switch (arguments.length - 1) { // <-- 1 is number of required arguments
                case 0:
                    optParam1 = 'Some default';
                case 1:
                    optParam2 = 'Another default';
                case 2:
                    optParam3 = 'Some other default';
            }
        }

        function ObjectFunction(args) {
            var defaults = {
                optParam1: 'Some default',
                optParam2: 'Another default',
                optParam3: 'Some other default'
            }
            args = $.extend({}, defaults, args);
        }

        function LogicalOrFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 || (optParam1 = 'Some default');
            optParam2 || (optParam1 = 'Another default');
            optParam3 || (optParam1 = 'Some other default');
        }
    };
</script>

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