Czy istnieje lepszy sposób na wykonanie opcjonalnych parametrów funkcji w JavaScript? [duplikat]

to pytanie ma już odpowiedzi tutaj : Ustaw domyślną wartość parametru dla funkcji JavaScript (27 odpowiedzi) Zamknięty 4 lata temu .

Zawsze obsługiwałem opcjonalne parametry w JavaScript w następujący sposób:

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

  // Do stuff
}
Czy jest na to lepszy sposób?

Czy są jakieś przypadki, w których użycie || w taki sposób nie powiedzie się?

Author: Peter Mortensen, 2008-09-29

28 answers

Twoja logika nie powiedzie się, jeśli zostanie przekazana opcja optionalArg, ale zostanie oceniona jako false-spróbuj tego jako alternatywa

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

Lub alternatywny idiom:

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

Użyj tego idiomu, który najlepiej przekaże ci intencję!

 1080
Author: Paul Dixon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-09 08:56:56

W ECMAScript 2015 (aka" ES6") możesz zadeklarować domyślne wartości argumentów w deklaracji funkcji:

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

Więcej o nich w Ten artykuł na MDN .

Jest to obecnie obsługiwane tylko przez Firefoksa , ale ponieważ standard został ukończony, spodziewaj się szybkiej poprawy wsparcia.


Edytuj (2019-06-12):

Domyślne parametry są obecnie powszechnie obsługiwane przez nowoczesne przeglądarki.
Wszystkie wersje Internetu Explorer nie obsługuje tej funkcji. Jednakże Chrome, Firefox i Edge Obecnie go obsługują.

 161
Author: Lachlan Hunt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-17 18:34:33

Uważam, że jest to najprostszy, najbardziej czytelny sposób:

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

ODPOWIEDŹ Paula Dixona (moim skromnym zdaniem) jest mniej czytelna niż ta, ale sprowadza się do preferencji.

ODPOWIEDŹ Insina jest znacznie bardziej zaawansowana, ale o wiele bardziej przydatna dla dużych funkcji!

EDIT 11/17/2013 21: 33: stworzyłem pakiet dla Node.js, który ułatwia "przeciążanie" funkcji (metod) zwanych parametrycznymi.

 127
Author: trusktr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-18 05:40:18

Jeśli chcesz rzucić literalne NULL w, to możesz mieć pewne problemy. Poza tym, nie, myślę, że jesteś na dobrej drodze.

Inną metodą, którą niektórzy wybierają, jest pobranie tablicy zmiennych assoc iterującej przez listę argumentów. Wygląda trochę schludniej, ale wyobrażam sobie, że jest trochę (bardzo trochę) bardziej intensywny proces/pamięć.

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

    // ...
}
 45
Author: Oli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-12 15:42:47

Najlepiej, aby refaktor przekazywał obiekt i łączył go z domyślnym obiektem, więc kolejność przekazywania argumentów nie ma znaczenia (zobacz drugą sekcję tej Odpowiedzi poniżej).

Jeśli jednak chcesz czegoś szybkiego, niezawodnego, łatwego w użyciu i nieporęcznego, spróbuj tego:]}

Czysta szybka poprawka dla dowolnej liczby domyślnych argumentów

  • skaluje się elegancko: minimalny dodatkowy kod dla każdego nowego domyślnego
  • możesz go wkleić anywhere: wystarczy zmienić liczbę wymaganych args i zmiennych
  • jeśli chcesz przekazać undefined do argumentu o wartości domyślnej, w ten sposób zmienna zostanie ustawiona jako undefined. Większość innych opcji na tej stronie zastąpi undefined wartością domyślną.

Oto przykład podania wartości domyślnych dla trzech opcjonalnych argumentów (z dwoma wymaganymi argumentami)

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
  }

}

Simple demo. Jest to podobne do odpowiedzi roenvinga , ale łatwo rozszerzalne dla dowolnej liczby domyślnych argumentów, łatwiejsze do aktualizacji, a używając arguments Nie Function.arguments.


Przekazywanie i łączenie obiektów dla większej elastyczności

Powyższy kod, podobnie jak wiele sposobów wykonywania domyślnych argumentów, nie może przekazywać argumentów poza sekwencją, np. przekazując optionalC, ale pozostawiając optionalB, aby powrócić do domyślnego.

Dobrym rozwiązaniem jest przekazanie obiektów i scalenie z domyślnym obiektem. Jest to również dobre dla konserwacji (wystarczy zadbać o to, aby Twoje czytelny kod, dzięki czemu przyszli współpracownicy nie będą pozostawieni w niepewności co do ewentualnej zawartości przekazywanych obiektów).

Przykład użycia jQuery. Jeśli nie używasz jQuery, możesz zamiast tego użyć Podkreślnika _.defaults(object, defaults) lub przejrzyj te opcje :

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

Oto prosty przykład tego w działaniu.

 33
Author: user56reinstatemonica8,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:38

Możesz użyć do tego różnych schematów. Zawsze sprawdzałem argumenty.długość:

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

  ...

-- robiąc to, prawdopodobnie nie może zawieść, ale nie wiem, czy twój sposób ma szansę zawieść, teraz nie mogę wymyślić scenariusza, w którym faktycznie zawiedzie ...

I wtedy Paul dostarczył jeden nieudany scenariusz !-)

 18
Author: roenving,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 09:19:54

Podobnie jak odpowiedź Oli, używam obiektu argumentu i obiektu, który definiuje wartości domyślne. Z odrobiną cukru...

/**
 * 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
}

...to może być trochę milsze.

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)

Co jest fajnego w tej metodzie?

  • możesz pominąć dowolną liczbę argumentów - jeśli chcesz tylko nadpisać wartość jednego argumentu, możesz po prostu podać ten argument, zamiast jawnie przekazać undefined Kiedy, powiedzmy, że jest 5 argumentów i chcesz tylko dostosować ta ostatnia, podobnie jak inne sugerowane metody.
  • podczas pracy z funkcją konstruktora dla obiektu, który dziedziczy po innym, łatwo jest zaakceptować wszelkie argumenty wymagane przez konstruktor obiektu, z którego dziedziczysz, ponieważ nie musisz wymieniać tych argumentów w podpisie konstruktora, ani nawet podawać własnych wartości domyślnych (pozwól konstruktorowi obiektu nadrzędnego zrobić to za Ciebie, jak pokazano powyżej, gdy CharField wywoła Field's konstruktor).
  • Obiekty potomne w hierarchii dziedziczenia mogą dostosowywać argumenty dla swojego konstruktora nadrzędnego według własnego uznania, wymuszając własne wartości domyślne lub zapewniając, że określona wartość będzie zawsze .
 13
Author: Jonny Buchanan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-05 17:46:57

sprawdzanie typu luźnego

Łatwe do napisania, ale 0, '', false, null i undefined zostanie przekonwertowana na wartość domyślną, której nie można się spodziewać.

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

ścisłe sprawdzanie typu

Dłuższy, ale obejmuje większość przypadków. Jedynym przypadkiem, w którym błędnie przypisuje wartość domyślną, jest przekazanie undefined jako parametru.

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

sprawdzanie zmiennej arguments

Łapie wszystkie przypadki, ale jest najbardziej niezdarny do napisania.

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

ES6

Niestety w tej chwili ma bardzo słabą obsługę przeglądarki

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

}
 9
Author: Petr Hurtak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-16 17:31:00

Jeśli używasz defaults intensywnie, wydaje się to o wiele bardziej czytelne:

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

Po prostu zadeklaruj tę funkcję na globalnym escope.

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

Wzór użycia fruit = defaultValue(fruit,'Apple');

*PS możesz zmienić nazwę funkcji defaultValue na krótką nazwę, po prostu nie używaj default to słowo zarezerwowane w javascript.

 8
Author: Vitim.us,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-15 21:23:50

Z ES2015 / ES6 możesz skorzystać z Object.assign, które mogą zastąpić $.extend() lub _.defaults()

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

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

  // do stuff
}

Możesz również użyć domyślnych argumentów, takich jak ten

function myFunc(requiredArg, { message: 'Hello', color: 'red', importance: 1 } = {}) {
  // do stuff
}
 5
Author: Yann Bertrand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-02 11:05:36

Jestem przyzwyczajony do kilku podstawowych zmian w obsłudze zmiennych opcjonalnych. Czasami przydatne są wersje relaksacyjne.

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

Falsy domyślne używane ze zmienną a jest na przykład szeroko stosowane w kręgosłupie .js .

 4
Author: Matt Montag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 09:26:53

Jeśli używasz podkreślenia biblioteki (powinieneś, to niesamowita biblioteka):

_.defaults(optionalArg, 'defaultValue');
 3
Author: roo2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-22 23:59:46

Wylądował na tym pytaniu, szukając domyślnych parametrów w EcmaScript 2015 , a więc po prostu wspominając...

Z ES6 możemy wykonać domyślne parametry :

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

doSomething(); //"defaultValue"
doSomething("myvalue"); //"myvalue"
 2
Author: Kulbhushan Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-09 14:19:21

Podczas projektu zauważyłem, że za dużo się powtarzam z opcjonalnymi parametrami i ustawieniami, więc stworzyłem klasę, która obsługuje sprawdzanie typu i przypisuje domyślną wartość, co skutkuje schludnym i czytelnym kodem. Zobacz przykład i daj mi znać, jeśli to działa dla Ciebie.

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 : [];
}

Użycie tej klasy:

(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));
 2
Author: Bart Wttewaall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-23 10:52:48

Nie wiem dlaczego odpowiedź @ Paula jest zawyżona, ale Walidacja przeciwko null jest dobrym wyborem. Może bardziej afirmatywny przykład będzie miał lepszy sens:

W JavaScript pominięty parametr jest jak zadeklarowana zmienna, która nie jest inicjalizowana (tylko var a1;). Operator równości konwertuje undefined na null, więc działa to świetnie zarówno z typami wartości, jak i obiektami, i w ten sposób CoffeeScript obsługuje opcjonalne parametry.

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

Choć istnieją obawy, że dla najlepsza semantyka to typeof variable === 'undefined' jest nieco lepsza. Nie zamierzam tego bronić, ponieważ to kwestia podstawowego API, jak funkcja jest implementowana; nie powinno to interesować użytkownika API.

Powinienem również dodać, że oto jedyny sposób, aby fizycznie upewnić się, że jakikolwiek argument został pominięty, używając operatora in, który niestety nie będzie działał z nazwami parametrów, więc trzeba przekazać indeks 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);
 2
Author: Arman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 09:24:02

Test na undefined jest niepotrzebny i nie jest tak solidny, jak mógłby być, ponieważ, jak zauważył user568458, dostarczone rozwiązanie nie powiedzie się, jeśli przejdzie null lub false. Użytkownicy twojego API mogą sądzić, że false lub null wymusi metody unikania tego parametru.

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

Wynik jest następujący:

defaultValue
provided
null
false
Te dwie ostatnie są potencjalnie złe. Zamiast tego spróbuj:
function bulletproof(required, optionalArg){
   optionalArg = optionalArg ? optionalArg : "defaultValue";;
   console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);

Co daje:

defaultValue
provided
defaultValue
defaultValue

Jedynym scenariuszem, w którym nie jest to optymalne, jest fakt, że masz opcjonalne parametry, które mają być booleanami lub celowym null.

 2
Author: slartibartfast,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 09:25:11

Wypróbowałem kilka opcji wymienionych tutaj i przetestowałem je pod kątem wydajności. W tej chwili logicalor wydaje się być najszybszy. Chociaż to podlega zmianom w czasie (różne wersje silnika JavaScript).

Oto moje wyniki (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

Ten test wydajności można łatwo odtworzyć na: http://jsperf.com/optional-parameters-typeof-vs-switch/2

Oto kod testu:

<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>
 2
Author: JDC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 09:30:44

Oto, z czym skończyłem:

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

Nazywa się tak:

WhoLikesCake({ b : "I do" });
 1
Author: NinjaFart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-29 21:26:17

Folks-

Po przyjrzeniu się tym i innym rozwiązaniom, wypróbowałem kilka z nich, używając jako bazy fragmentu kodu pochodzącego z W3Schools. To, co działa, znajdziesz poniżej. Każdy z komentowanych elementów działa również i w ten sposób pozwala Ci eksperymentować po prostu usuwając Indywidualne komentarze. Aby było jasne, parametr "eyecolor" nie jest zdefiniowany.

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."; 
 1
Author: Mark Funk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-13 20:53:23
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/

 1
Author: Imagine Breaker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-03 09:28:30

Oto moje rozwiązanie. Dzięki temu możesz zostawić dowolny parametr. Kolejność opcjonalnych parametrów nie jest ważna i można dodać walidację niestandardową.

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
Author: Duco L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-11 13:51:11
  1. arg || 'default' jest świetnym sposobem i działa w 90% przypadków

  2. To nie powiedzie się, gdy trzeba przekazać wartości, które mogą być "falsy"

    • false
    • 0
    • NaN
    • ""

    W takich przypadkach musisz być nieco bardziej gadatliwy i sprawdzić undefined

  3. Należy również uważać, gdy najpierw masz opcjonalne argumenty, musisz być świadomy typów wszystkich swoich argumentów

 1
Author: mcfedr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-30 19:36:34

We wszystkich przypadkach, gdy optionalArg jest falsy, skończysz z 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);

Wszystkie powyższe log defaultValue, ponieważ wszystkie 6 są fałszywe. W przypadku 4, 5, 6 możesz nie być zainteresowany ustawieniem optionalArg jako defaultValue, ale ustawia, ponieważ są fałszywe.

 1
Author: Pavan Varanasi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 09:42:00

Popraw mnie jeśli się mylę, ale to chyba najprostszy sposób (przynajmniej na jeden argument):

function myFunction(Required,Optional)
{
    if (arguments.length<2) Optional = "Default";
    //Your code
}
 0
Author: Brian McCutchon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-14 05:18:19

Te są krótsze od wersji operatora typeof.

function foo(a, b) {
    a !== undefined || (a = 'defaultA');
    if(b === undefined) b = 'defaultB';
    ...
}
 0
Author: Aurélien Ooms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-07 18:05:53

Proponuję użyć ArgueJS w ten sposób:

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

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

}

Możesz również zastąpić undefined przez typ argumentu, który chcesz otrzymać, w następujący sposób:

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

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

}
 -1
Author: zVictor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-12 15:35:28

Wydaje się, że najbezpieczniejszym sposobem-radzić sobie z każdym \ falsy types dostarczonych argumentów przed podjęciem decyzji o wykorzystaniu default - jest sprawdzenie istnienia\obecności opcjonalnego argumentu w wywołanej funkcji.

Opierając się na arguments object member creation, który nawet nie zostanie utworzony, jeśli brakuje argumentu, niezależnie od tego, że może być zadeklarowany, możemy napisać twoją funkcję jak to:

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

Wykorzystanie tego zachowania: Możemy bezpiecznie sprawdzić brakujące wartości na liście argumentów arbitralnie i jawnie, gdy chcemy się upewnić, że funkcja otrzyma określoną wartość wymaganą w jej procedurze.

W poniższym kodzie demo celowo umieścimy typeless i valueless undefined jako wartość domyślna, aby móc określić, czy może się nie udać na falsy wartości argumentów, takich jak 0 false itd. lub jeśli zachowuje się zgodnie z oczekiwaniami.

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

Teraz, sprawdzając kilka fałszywych wartości argumentów, aby sprawdzić, czy ich obecność jest poprawnie wykryta i dlatego ocenia do prawda:

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

Co oznacza -nie zawiedli rozpoznawania / as expected argument values. Tutaj mamy sprawdzanie z pominięciem wszystkich argumentów, które zgodnie z naszym algo powinny uzyskać swoje domyślne wartości, nawet jeśli są falsy.

argCheck( );
>> undefined false 0 null

Jak widzimy, argumenty arg1, arg2, arg3 i nierejestrowane arg4 zwracają swoje dokładne default wartości, zgodnie z zamówieniem. Ponieważ teraz upewniliśmy się, że działa, możemy przepisać funkcję, która będzie w stanie z niej korzystać tak, jak w pierwszym przykładzie, używając: albo jeśli lub ternary warunek.

Na funkcjach, które mają więcej niż jeden opcjonalny argument, - a loop through, może zapisać nam kilka bitów. Ale od kłótni nazwy nie otrzymuj inicjalizacji, jeśli ich wartości nie są podane, nie możemy uzyskać do nich dostępu nazwami, nawet jeśli programowo napisaliśmy wartość domyślną, możemy uzyskać do nich dostęp tylko za pomocą argumentów [index], które są bezużyteczną czytelnością kodu.

Ale pomijając tę niedogodność, która w pewnych sytuacjach kodowania może być w pełni akceptowalna, jest jeszcze jeden nierozliczony problem dla wielu i arbitralnej liczby domyślnych argumentów. Które mogą i powinny być uważane za błąd, ponieważ nie możemy już pomijać argumentów, jak kiedyś mogliśmy być w stanie, bez podawania wartości, w składni takiej jak:

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

Bo rzuci! Co uniemożliwia nam zastąpienie naszego argumentu określonym typem falsy pożądanej wartości domyślnej. Co jest głupie, ponieważ obiekt arguments jest obiektem podobnym do tablicy i oczekuje się, że będzie obsługiwał tę składnię i Konwencję tak, jak jest, natywnie lub domyślnie!

Ponieważ ta krótkowzroczna decyzja nie może już mieć nadziei na napisanie takiej funkcji:

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

W takim przypadku będziemy w stanie zapisać każdą domyślną wartość pożądanego typu w wierszu arguments i będziemy mogli przynajmniej uzyskać do nich dostęp przez args.indeks.

Na przykład wywołanie tej funkcji dałoby:

argCheck();
>>undefined 0 false null

Zgodnie z naszą domyślną tablicą wartości argumentów. Jednak nadal możliwe jest:

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

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

Ale niestety nie:

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

Które w przeciwnym razie logowanie:

>>a 0 false 22

Ale To jest w lepszym świecie! Jednak - w przypadku pierwotnego pytania-najwyższa funkcja sprawdzi się dobrze. np.:

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

P. s.: przepraszam, że nie zachowuję typów wybranych wartości domyślnych w moich wejściach argumentów podczas ich zapisywania.

 -1
Author: Bekim Bacaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-29 03:44:18
function foo(requiredArg){
  if(arguments.length>1) var optionalArg = arguments[1];
}
 -2
Author: Dustin Poissant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-22 23:59:10