Esiste un modo migliore per eseguire parametri di funzione opzionali in JavaScript? [duplicare]

StackOverflow https://stackoverflow.com/questions/148901

  •  02-07-2019
  •  | 
  •  

Domanda

    

Questa domanda ha già una risposta qui:

         

Ho sempre gestito parametri opzionali in JavaScript in questo modo:

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

  // Do stuff
}

C'è un modo migliore per farlo?

Ci sono casi in cui l'uso di || in questo modo fallirà?

È stato utile?

Soluzione

La tua logica ha esito negativo se viene passato optionalArg, ma viene valutato come falso - prova questo come alternativa

if (typeof optionalArg === 'undefined') { optionalArg = 'default'; }

O un linguaggio alternativo:

optionalArg = (typeof optionalArg === 'undefined') ? 'default' : optionalArg;

Usa il linguaggio che ti comunica l'intento migliore per te!

Altri suggerimenti

In ECMAScript 2015 (aka "quotazione ES6") è possibile dichiarare i valori degli argomenti predefiniti nella dichiarazione della funzione:

function myFunc(requiredArg, optionalArg = 'defaultValue') {
    // do stuff
}

Maggiori informazioni su questo articolo su MDN .

Questo è attualmente supportato solo da Firefox , ma come lo standard è stato completato, prevediamo che il supporto migliorerà rapidamente.

EDIT (2019-06-12):

I parametri predefiniti sono ora ampiamente supportati dai browser moderni. Tutte le versioni di Internet Explorer non supportano questa funzione. Tuttavia, Chrome, Firefox e Edge attualmente lo supportano.

Trovo che questo sia il modo più semplice e più leggibile:

if (typeof myVariable === 'undefined') { myVariable = 'default'; }
//use myVariable here

La risposta di Paul Dixon (secondo la mia modesta opinione) è meno leggibile di così, ma si riduce alle preferenze.

La risposta di insin è molto più avanzata, ma molto più utile per le grandi funzioni!

MODIFICA 17/11/2013 21:33: ho creato un pacchetto per Node.js che semplifica " sovraccarico " funzioni (metodi) chiamate parametric .

Se hai bisogno di inserire un NULL letterale, potresti avere dei problemi. A parte questo, no, penso che tu sia probabilmente sulla strada giusta.

L'altro metodo che alcune persone scelgono è quello di prendere un array assoc di variabili che scorre l'elenco degli argomenti. Sembra un po 'più ordinato ma immagino che sia un po' (molto poco) un po 'più intenso di processo / memoria.

function myFunction (argArray) {
    var defaults = {
        'arg1'  :   "value 1",
        'arg2'  :   "value 2",
        'arg3'  :   "value 3",
        'arg4'  :   "value 4"
    }

    for(var i in defaults) 
        if(typeof argArray[i] == "undefined") 
               argArray[i] = defaults[i];

    // ...
}

Idealmente, si farebbe il refactor per passare un oggetto e unirlo con un oggetto predefinito, quindi l'ordine in cui gli argomenti vengono passati non ha importanza (vedere la seconda sezione di questa risposta, di seguito).

Se, tuttavia, vuoi solo qualcosa di veloce, affidabile, facile da usare e non ingombrante, prova questo:


Una soluzione rapida per qualsiasi numero di argomenti predefiniti

  • Ridimensiona elegantemente: codice extra minimo per ogni nuovo valore predefinito
  • Puoi incollarlo ovunque: basta cambiare il numero di argomenti e variabili richiesti
  • Se si desidera passare undefined a un argomento con un valore predefinito, in questo modo, la variabile viene impostata come undefined . La maggior parte delle altre opzioni in questa pagina sostituisce undefined con il valore predefinito.

Ecco un esempio per fornire valori predefiniti per tre argomenti opzionali (con due argomenti obbligatori)

function myFunc( requiredA, requiredB,  optionalA, optionalB, optionalC ) {

  switch (arguments.length - 2) { // 2 is the number of required arguments
    case 0:  optionalA = 'Some default';
    case 1:  optionalB = 'Another default';
    case 2:  optionalC = 'Some other default';
    // no breaks between cases: each case implies the next cases are also needed
  }

}

Demo semplice . È simile a risposta di roenving , ma facilmente estensibile per qualsiasi numero di argomenti predefiniti, più facile da aggiornare e utilizzando argomenti non Function.arguments .


Passaggio e unione di oggetti per una maggiore flessibilità

Il codice sopra, come molti modi di fare argomenti predefiniti, non può passare argomenti fuori sequenza, ad esempio, passando optionalC ma lasciando optionalB per tornare al suo predefinito.

Una buona opzione è quella di passare oggetti e unirli con un oggetto predefinito. Questo è anche un bene per la manutenibilità (fai solo attenzione a mantenere il tuo codice leggibile, così i futuri collaboratori non rimarranno indovinati sui possibili contenuti degli oggetti che passi intorno).

Esempio usando jQuery. Se non si utilizza jQuery, è possibile utilizzare invece _.defaults (oggetto, impostazioni predefinite) o sfoglia queste opzioni :

function myFunc( args ) {
  var defaults = {
    optionalA: 'Some default',
    optionalB: 'Another default',
    optionalC: 'Some other default'
  };
  args = $.extend({}, defaults, args);
}

Ecco un semplice esempio di ciò in azione .

Puoi usare alcuni schemi diversi per quello. Ho sempre provato per argomenti.length:

function myFunc(requiredArg, optionalArg){
  optionalArg = myFunc.arguments.length<2 ? 'defaultValue' : optionalArg;

  ...

- in questo modo, non può assolutamente fallire, ma non so se la tua strada abbia qualche possibilità di fallire, proprio ora non riesco a inventare uno scenario, in cui in realtà fallirebbe ...

E poi Paul ha fornito uno scenario fallimentare! -)

Simile alla risposta di Oli, utilizzo un argomento Object e un Object che definisce i valori predefiniti. Con un po 'di zucchero ...

/**
 * Updates an object's properties with other objects' properties. All
 * additional non-falsy arguments will have their properties copied to the
 * destination object, in the order given.
 */
function extend(dest) {
  for (var i = 1, l = arguments.length; i < l; i++) {
    var src = arguments[i]
    if (!src) {
      continue
    }
    for (var property in src) {
      if (src.hasOwnProperty(property)) {
        dest[property] = src[property]
      }
    }
  }
  return dest
}

/**
 * Inherit another function's prototype without invoking the function.
 */
function inherits(child, parent) {
  var F = function() {}
  F.prototype = parent.prototype
  child.prototype = new F()
  child.prototype.constructor = child
  return child
}

... questo può essere reso un po 'più bello.

function Field(kwargs) {
  kwargs = extend({
    required: true, widget: null, label: null, initial: null,
    helpText: null, errorMessages: null
  }, kwargs)
  this.required = kwargs.required
  this.label = kwargs.label
  this.initial = kwargs.initial
  // ...and so on...
}

function CharField(kwargs) {
  kwargs = extend({
    maxLength: null, minLength: null
  }, kwargs)
  this.maxLength = kwargs.maxLength
  this.minLength = kwargs.minLength
  Field.call(this, kwargs)
}
inherits(CharField, Field)

Cosa c'è di bello in questo metodo?

  • Puoi omettere tutti gli argomenti che desideri: se vuoi solo sovrascrivere il valore di un argomento, puoi semplicemente fornire quell'argomento, invece di dover passare esplicitamente undefined quando, dì lì sono 5 argomenti e desideri personalizzare solo l'ultimo, come avresti a che fare con alcuni degli altri metodi suggeriti.
  • Quando si lavora con una funzione di costruzione per un oggetto che eredita da un altro, è facile accettare qualsiasi argomento richiesto dal costruttore dell'oggetto da cui si eredita, poiché non è necessario nominare tali argomenti nel proprio firma del costruttore, o anche fornire i propri valori predefiniti (lasciare che il costruttore dell'oggetto principale lo faccia per te, come visto sopra quando CharField chiama il costruttore di Field ).
  • Gli oggetti figlio nelle gerarchie di ereditarietà possono personalizzare gli argomenti per il loro costruttore genitore nel modo che ritengono opportuno, applicando i propri valori predefiniti o garantendo che un certo valore sarà sempre utilizzato .

Se si utilizzano ampiamente le impostazioni predefinite, questo sembra molto più leggibile:

function usageExemple(a,b,c,d){
    //defaults
    a=defaultValue(a,1);
    b=defaultValue(b,2);
    c=defaultValue(c,4);
    d=defaultValue(d,8);

    var x = a+b+c+d;
    return x;
}

Dichiara semplicemente questa funzione sull'escope globale.

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

Schema di utilizzo fruit = defaultValue (fruit, 'Apple');

* PS puoi rinominare la funzione defaultValue con un nome breve, ma non usare default è una parola riservata in javascript.

Controllo del tipo sciolto

Facile da scrivere, ma 0 , '' , false , null e non definito verrà convertito nel valore predefinito, che potrebbe non essere previsto.

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

Controllo rigoroso del tipo

Più a lungo, ma copre la maggior parte dei casi. L'unico caso in cui assegna erroneamente il valore predefinito è quando passiamo undefined come parametro.

function myFunc(requiredArg, optionalArg) {
    optionalArg = typeof optionalArg !== 'undefined' ? optionalArg : 'defaultValue';
}

Verifica della variabile argomenti

Cattura tutti i casi ma è il più goffo da scrivere.

function myFunc(requiredArg, optionalArg1, optionalArg2) {
    optionalArg1 = arguments.length > 1 ? optionalArg1 : 'defaultValue';
    optionalArg2 = arguments.length > 2 ? optionalArg2 : 'defaultValue';
}

ES6

Purtroppo, al momento, il supporto del browser è molto scarso

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

}

Con ES2015 / ES6 puoi sfruttare Object.assign che può sostituire $ .extend () o _.defaults ()

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

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

  // do stuff
}

Puoi anche usare argomenti predefiniti come questo

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

Sono abituato a vedere alcune variazioni di base sulla gestione delle variabili opzionali. A volte, le versioni rilassate sono utili.

function foo(a, b, c) {
  a = a || "default";   // Matches 0, "", null, undefined, NaN, false.
  a || (a = "default"); // Matches 0, "", null, undefined, NaN, false.

  if (b == null) { b = "default"; } // Matches null, undefined.

  if (typeof c === "undefined") { c = "default"; } // Matches undefined.
}

L'impostazione predefinita di falsa utilizzata con la variabile a è, ad esempio, ampiamente utilizzata in Backbone.js .

Se stai usando la Underscore (dovresti, è una libreria fantastica):

_.defaults(optionalArg, 'defaultValue');

Soddisfatto di questa domanda, cercando parametri predefiniti in EcmaScript 2015 , citando quindi solo ...

Con ES6 possiamo fare parametri predefiniti :

function doSomething(optionalParam = "defaultValue"){
    console.log(optionalParam);//not required to check for falsy values
}

doSomething(); //"defaultValue"
doSomething("myvalue"); //"myvalue"

Durante un progetto ho notato che mi stavo ripetendo troppo con i parametri e le impostazioni opzionali, quindi ho creato una classe che gestisce il controllo del tipo e assegna un valore predefinito che risulta in un codice pulito e leggibile. Vedi esempio e fammi sapere se questo funziona per te.

var myCar           = new Car('VW', {gearbox:'automatic', options:['radio', 'airbags 2x']});
var myOtherCar      = new Car('Toyota');

function Car(brand, settings) {
    this.brand      = brand;

    // readable and adjustable code
    settings        = DefaultValue.object(settings, {});
    this.wheels     = DefaultValue.number(settings.wheels, 4);
    this.hasBreaks  = DefaultValue.bool(settings.hasBreaks, true);
    this.gearbox    = DefaultValue.string(settings.gearbox, 'manual');
    this.options    = DefaultValue.array(settings.options, []);

    // instead of doing this the hard way
    settings        = settings || {};
    this.wheels     = (!isNaN(settings.wheels)) ? settings.wheels : 4;
    this.hasBreaks  = (typeof settings.hasBreaks !== 'undefined') ? (settings.hasBreaks === true) : true;
    this.gearbox    = (typeof settings.gearbox === 'string') ? settings.gearbox : 'manual';
    this.options    = (typeof settings.options !== 'undefined' && Array.isArray(settings.options)) ? settings.options : [];
}

Uso di questa classe:

(function(ns) {

    var DefaultValue = {

        object: function(input, defaultValue) {
            if (typeof defaultValue !== 'object') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? input : defaultValue;
        },

        bool: function(input, defaultValue) {
            if (typeof defaultValue !== 'boolean') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (input === true) : defaultValue;
        },

        number: function(input, defaultValue) {
            if (isNaN(defaultValue)) throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined' && !isNaN(input)) ? parseFloat(input) : defaultValue;
        },

        // wrap the input in an array if it is not undefined and not an array, for your convenience
        array: function(input, defaultValue) {
            if (typeof defaultValue === 'undefined') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (Array.isArray(input) ? input : [input]) : defaultValue;
        },

        string: function(input, defaultValue) {
            if (typeof defaultValue !== 'string') throw new Error('invalid defaultValue type');
            return (typeof input === 'string') ? input : defaultValue;
        },

    };

    ns.DefaultValue = DefaultValue;

}(this));

Non so perché la risposta di @ Paul sia stata sottoposta a downgrade, ma la convalida contro null è una buona scelta. Forse un esempio più affermativo avrà più senso:

In JavaScript un parametro perso è come una variabile dichiarata che non è inizializzata (solo var a1; ). E l'operatore di uguaglianza converte il non definito in null, quindi funziona benissimo sia con i tipi di valore che con gli oggetti, ed è così che CoffeeScript gestisce i parametri opzionali.

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...';
    //...
}

Tuttavia, vi sono dubbi sul fatto che per la migliore semantica sia typeof variabile === 'undefined' è leggermente migliore. Non ho intenzione di difenderlo poiché è la questione dell'API sottostante come viene implementata una funzione; non dovrebbe interessare l'utente dell'API.

Dovrei anche aggiungere che qui è l'unico modo per assicurarsi fisicamente di aver perso qualsiasi argomento, usando l'operatore in che purtroppo non funzionerà con i nomi dei parametri, quindi è necessario passare un indice del argomenti .

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);

Il test per undefined non è necessario e non è così solido come potrebbe essere perché, come sottolineato da user568458, la soluzione fornita fallisce se viene passato null o false. Gli utenti della tua API potrebbero pensare che false o null forzino il metodo per evitare quel parametro.

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

Il risultato è:

defaultValue
provided
null
false

Questi ultimi due sono potenzialmente cattivi. Prova invece:

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

Che risulta in:

defaultValue
provided
defaultValue
defaultValue

L'unico scenario in cui questo non è ottimale è quando in realtà hai parametri opzionali che sono pensati per essere booleani o nulli intenzionali.

Ho provato alcune opzioni menzionate qui e le prestazioni le hanno testate. In questo momento il logico sembra essere il più veloce. Anche se questo è soggetto a modifiche nel tempo (diverse versioni del motore JavaScript).

Questi sono i miei risultati (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

Questo test delle prestazioni può essere facilmente replicato su: http://jsperf.com/optional-parameters-typeof-vs-switch/ 2

Questo è il codice del test:

<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>

Questo è quello che ho finito con:

function WhoLikesCake(options) {
  options = options || {};
  var defaultOptions = {
    a : options.a || "Huh?",
    b : options.b || "I don't like cake."
  }
  console.log('a: ' + defaultOptions.b + ' - b: ' + defaultOptions.b);

  // Do more stuff here ...
}

Chiamato così:

WhoLikesCake({ b : "I do" });

Gente -

Dopo aver esaminato queste e altre soluzioni, ho provato alcune di esse usando come base un frammento di codice originario di W3Schools. Puoi trovare ciò che funziona di seguito. Anche tutti gli articoli commentati funzionano e sono in questo modo per permetterti di sperimentare semplicemente rimuovendo i singoli commenti. Per essere chiari, è il "eyecolor" parametro che non viene definito.

function person(firstname, lastname, age, eyecolor)
{
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
this.eyecolor = eyecolor;
// if(null==eyecolor)
//   this.eyecolor = "unknown1";
//if(typeof(eyecolor)==='undefined') 
//   this.eyecolor = "unknown2";
// if(!eyecolor)
//   this.eyecolor = "unknown3";
this.eyecolor = this.eyecolor || "unknown4";
}

var myFather = new person("John", "Doe", 60);
var myMother = new person("Sally", "Rally", 48, "green");

var elem = document.getElementById("demo");
elem.innerHTML = "My father " +
              myFather.firstname + " " +
              myFather.lastname + " is " +
              myFather.age + " with " +
              myFather.eyecolor + " eyes.<br/>" +
              "My mother " +
              myMother.firstname + " " +
              myMother.lastname + " is " +
              myMother.age + " with " +
              myMother.eyecolor + " eyes."; 
function Default(variable, new_value)
{
    if(new_value === undefined) { return (variable === undefined) ? null : variable; }
    return (variable === undefined) ? new_value : variable;
}

var a = 2, b = "hello", c = true, d;

var test = Default(a, 0),
test2 = Default(b, "Hi"),
test3 = Default(c, false),
test4 = Default(d, "Hello world");

window.alert(test + "\n" + test2 + "\n" + test3 + "\n" + test4);

http://jsfiddle.net/mq60hqrf/

Ecco la mia soluzione. Con questo puoi lasciare qualsiasi parametro tu voglia. L'ordine dei parametri opzionali non è importante ed è possibile aggiungere la convalida personalizzata.

function YourFunction(optionalArguments) {
            //var scope = this;

            //set the defaults
            var _value1 = 'defaultValue1';
            var _value2 = 'defaultValue2';
            var _value3 = null;
            var _value4 = false;

            //check the optional arguments if they are set to override defaults...
            if (typeof optionalArguments !== 'undefined') {

                if (typeof optionalArguments.param1 !== 'undefined')
                    _value1 = optionalArguments.param1;

                if (typeof optionalArguments.param2 !== 'undefined')
                    _value2 = optionalArguments.param2;

                if (typeof optionalArguments.param3 !== 'undefined')
                    _value3 = optionalArguments.param3;

                if (typeof optionalArguments.param4 !== 'undefined')
                    //use custom parameter validation if needed, in this case for javascript boolean
                   _value4 = (optionalArguments.param4 === true || optionalArguments.param4 === 'true');
            }

            console.log('value summary of function call:');
            console.log('value1: ' + _value1);
            console.log('value2: ' + _value2);
            console.log('value3: ' + _value3);
            console.log('value4: ' + _value4);
            console.log('');
        }


        //call your function in any way you want. You can leave parameters. Order is not important. Here some examples:
        YourFunction({
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
            param3: 'yourGivenValue3',
            param4: true,
        });

        //order is not important
        YourFunction({
            param4: false,
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
        });

        //uses all default values
        YourFunction();

        //keeps value4 false, because not a valid value is given
        YourFunction({
            param4: 'not a valid bool'
        });
  1. arg || 'default' è un ottimo modo e funziona per il 90% dei casi

  2. Non riesce quando è necessario passare valori che potrebbero essere "falsi"

    • false
    • 0
    • NaN
    • " "

    Per questi casi dovrai essere un po 'più prolisso e controllare undefined

  3. Fai anche attenzione quando prima hai argomenti opzionali, devi essere consapevole dei tipi di tutti i tuoi argomenti

In tutti i casi in cui optionalArg è errato, finirai con defaultValue.

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
    console.log(optionalArg);
    // Do stuff
}
myFunc(requiredArg);
myFunc(requiredArg, null);
myFunc(requiredArg, undefined);
myFunc(requiredArg, "");
myFunc(requiredArg, 0);
myFunc(requiredArg, false);

Tutti i precedenti log defaultValue, perché tutti e 6 sono falsi. Nel caso 4, 5, 6 potresti non essere interessato a impostare optionalArg come defaultValue, ma si imposta poiché sono falsi.

Correggimi se sbaglio, ma questo sembra il modo più semplice (per un argomento, comunque):

function myFunction(Required,Optional)
{
    if (arguments.length<2) Optional = "Default";
    //Your code
}

Questi sono più corti della versione dell'operatore typeof.

function foo(a, b) {
    a !== undefined || (a = 'defaultA');
    if(b === undefined) b = 'defaultB';
    ...
}

Ti suggerisco di usare ArgueJS in questo modo:

function myFunc(){
  arguments = __({requiredArg: undefined, optionalArg: [undefined: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

Puoi anche sostituire undefined con il tipo di argomento che ti aspetti di ricevere, in questo modo:

function myFunc(){
  arguments = __({requiredArg: Number, optionalArg: [String: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

Sembra che sia il modo più sicuro - per gestire tutti \ eventuali tipi di falsi di argomenti forniti prima di decidere di utilizzare il predefinito : verifica l'esistenza \ presenza dell'argomento argomento facoltativo nella funzione invocata.

Basandosi sulla creazione del membro dell'oggetto degli argomenti che non viene nemmeno creata se manca l'argomento, indipendentemente dal fatto che possa essere dichiarato, possiamo scrivere la tua funzione in questo modo:

  function myFunc(requiredArg, optionalArg){
        optionalArg = 1 in arguments ? optionalArg : 'defaultValue';
  //do stuff
  }

Utilizzando questo comportamento: Possiamo verificare in modo sicuro la presenza di valori mancanti nell'elenco degli argomenti in modo arbitrario ed esplicito ogni volta che dobbiamo assicurarci che la funzione ottenga un determinato valore richiesto nella sua procedura.

Nel seguente codice demo inseriremo deliberatamente un senza tipo e senza valore non definito come valore predefinito essere in grado di determinare se potrebbe non riuscire su valori di argomento falsi, come 0 false ecc., o se si comporta come previsto.

function argCheck( arg1, arg2, arg3 ){

       arg1 = 0 in arguments || undefined;
       arg2 = 1 in arguments || false;
       arg3 = 2 in arguments || 0;
   var arg4 = 3 in arguments || null;

   console.log( arg1, arg2, arg3, arg4 ) 
}

Ora, controllando alcuni valori dell'argomento falsi per vedere se la loro presenza viene rilevata correttamente e quindi valuta true :

argCheck( "", 0, false, null );
>> true true true true

Il che significa che non hanno fallito il riconoscimento di / come valori di argomento previsti. Qui abbiamo un controllo con tutti gli argomenti mancanti, che secondo il nostro algo dovrebbero acquisire i loro valori predefiniti anche se sono falsi .

argCheck( );
>> undefined false 0 null

Come possiamo vedere, gli argomenti arg1, arg2, arg3 e il arg4 non dichiarato, stanno restituendo il loro esatto default valori, come ordinato. Poiché ora ci siamo assicurati che funzioni, possiamo riscrivere la funzione che sarà effettivamente in grado di usarli come nel primo esempio usando: if o un ternario condizione.

Sulle funzioni che hanno più di un argomento opzionale, - un loop through, potrebbe averci salvato alcuni bit. Ma poiché l'argomento nomi non viene inizializzato se i loro valori non vengono forniti, non possiamo più accedervi con i nomi anche se abbiamo programmato un valore predefinito, possiamo accedervi solo tramite argomenti [indice] che la leggibilità del codice è inutile.

Ma a parte questo inconveniente, che in alcune situazioni di codifica potrebbe essere pienamente accettabile, c'è un altro problema non contabilizzato per un numero multiplo e arbitrario di valori predefiniti dell'argomento. Che può e deve essere considerato un bug, poiché non possiamo più saltare argomenti, come avremmo potuto una volta, senza dare un valore, in una sintassi come:

argCheck("a",,22,{});

perché lancerà! Il che rende impossibile per noi sostituire il nostro argomento con uno specifico tipo falsy del nostro valore predefinito desiderato. Il che è stupido, dal momento che oggetto argomenti è un oggetto simile ad un array e dovrebbe supportare questa sintassi e convenzione così com'è, nativamente o di default!

A causa di questa decisione miope non possiamo più sperare di scrivere una funzione come questa:

function argCheck( ) {
    var _default = [undefined, 0, false, null ],
        _arg = arguments;

 for( var x in _default ) {
         x in _arg ? 1 : _arg[x] = _default[x];
        }
    console.log( _arg[0],_arg[1],_arg[2],_arg[3] );
}

nel qual caso, saremmo in grado di scrivere ogni valore predefinito di un tipo desiderato nella riga degli argomenti e potremmo almeno accedervi tramite args.index.

Ad esempio questa chiamata di funzione produrrebbe:

argCheck();
>>undefined 0 false null

come definito nel nostro array predefinito di valori argomenti. Tuttavia è ancora possibile:

argCheck({})
>>Object {  } 0 false null

argCheck({}, [])
>>Object {  } Array [  ] false null

Ma purtroppo no:

 argCheck("a",,,22);
 >>SyntaxError: expected expression, got ','

Che altrimenti verrebbe registrato:

>>a 0 false 22

ma quello è in un mondo migliore! Tuttavia, per la domanda originale, la funzione più in alto andrà bene. per esempio:.

function argCheck( arg, opt ) {
         1 in arguments ? 1 : opt = "default";
         console.log( arg, opt );
}

p.s .: scusate per non aver preservato i tipi delle impostazioni predefinite scelte negli input del mio argomento durante la scrittura.

function foo(requiredArg){
  if(arguments.length>1) var optionalArg = arguments[1];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top