Pytanie Ustaw domyślną wartość parametru dla funkcji JavaScript


Chciałbym, aby funkcja JavaScript miała opcjonalne argumenty, które ustawiłem jako domyślne, które zostaną użyte, jeśli wartość nie jest zdefiniowana. W Ruby możesz to zrobić tak:

def read_file(file, delete_after = false)
  # code
end

Czy to działa w JavaScript?

function read_file(file, delete_after = false) {
  // Code
}

2022
2018-05-21 20:07


pochodzenie




Odpowiedzi:


Od wersji ES6 / ES2015 domyślne parametry podano w specyfikacji językowej.

function read_file(file, delete_after = false) {
  // Code
}

po prostu działa.

Odniesienie: Parametry domyślne - MDN

Domyślne parametry funkcji umożliwiają inicjalizację parametrów formalnych za pomocą wartości domyślnych, jeśli bez wartości lub niezdefiniowany jest przekazywane.

Możesz również symulacja domyślna o imieniu parametry poprzez destrukturyzację:

// the `= {}` below lets you call the function without any parameters
function myFor({ start = 5, end = 1, step = -1 } = {}) { // (A)
    // Use the variables `start`, `end` and `step` here
    ···
}

Pre ES2015,

Istnieje wiele sposobów, ale jest to moja preferowana metoda - pozwala przekazywać wszystko, co chcesz, w tym fałsz lub zero. (typeof null == "object")

function foo(a, b) {
  a = typeof a !== 'undefined' ? a : 42;
  b = typeof b !== 'undefined' ? b : 'default_b';
  ...
}

2937
2018-05-21 20:10



Możesz również hermetyzować go jako taki: function defaultFor(arg, val) { return typeof arg !== 'undefined' ? arg : val; } a potem możesz to nazwać a = defaultFor(a, 42); - Camilo Martin
@SiPlus i masz dodatkowe błędy referencyjne za darmo podczas próby użycia undefined obiekty: p Nawet jeśli może działać z niektórymi przeglądarkami i może być szybszy, null jest nadal obiektem i undefined jest odniesieniem do typu pierwotnego, który próbuje powiedzieć, że nie ma tu nic, nawet nie null. Zobacz tutaj, oba przypadki w pigułce: JavaScript / Reference / Global_Objects / undefined. - Sampo Sarrala
jeśli sprawdzisz własność obiektu, to typeof jest zbędny. function foo(data) { var bar = data.bar !== undefined ? data.bar : 'default'; } Nie spowoduje to błędów referencyjnych i jest zwięzły. - Dziamid
Wiem, że to naprawdę niewielkie, ale nie podoba mi się to, jak to przypisujesz a = a i b = b gdy te parametry nie są niezdefiniowane. Również ten potrójny operator o nieco skomplikowanym stanie może być trudny do odczytania dla przyszłych opiekunów. Wolałbym następującą składnię: if (typeof a == 'undefined') a = 42 - bez niepotrzebnego zadania i trochę łatwiejsze do odczytania. - Daddy32
Czy istnieje jakiś powód do użycia? typeof? Łatwiej byłoby po prostu zrobić a === undefined. Plus w ten sposób pojawi się błąd referencyjny, jeśli błędnie napisałeś undefined vs. wstawianie go w łańcuch. - Abe Voelker


function read_file(file, delete_after) {
    delete_after = delete_after || "my default here";
    //rest of code
}

Przypisuje to delete_after wartość delete_after jeśli nie jest falsey wartość inaczej przydziela ciąg znaków "my default here". Aby uzyskać więcej szczegółów, sprawdź Doug Crockford za badanie języka i sprawdź sekcję o operatorach.

To podejście nie działa, jeśli chcesz przekazać falsey wartość np. false, null, undefined, 0 lub "". Jeśli potrzebujesz falsey wartości, które należy przekazać, wymagałyby użycia metody Odpowiedź Toma Rittera.

Gdy mamy do czynienia z pewną liczbą parametrów funkcji, często przydatne jest umożliwienie konsumentowi przekazania argumentów parametru w obiekcie, a następnie łączyć te wartości z obiektem zawierającym domyślne wartości funkcji

function read_file(values) {
    values = merge({ 
        delete_after : "my default here"
    }, values || {});

    // rest of code
}

// simple implementation based on $.extend() from jQuery
function merge() {
    var obj, name, copy,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length;

    for (; i < length; i++) {
        if ((obj = arguments[i]) != null) {
            for (name in obj) {
                copy = obj[name];

                if (target === copy) {
                    continue;
                }
                else if (copy !== undefined) {
                    target[name] = copy;
                }
            }
        }
    }

    return target;
};

używać

// will use the default delete_after value
read_file({ file: "my file" }); 

// will override default delete_after value
read_file({ file: "my file", delete_after: "my value" }); 

559
2018-05-21 20:09



Uważam to za niewystarczające, ponieważ mogę chcieć przekazać fałszywe. - Tom Ritter
Uważam, że jest odpowiednia w większości sytuacji - Russ Cam
To również nie działa dla 0. :( - Alex Kahn
Nie działa dla żadnej wartości falsey - Russ Cam
Ponieważ nie działa w przypadku wartości falsey, może spowodować koszmar utrzymania. Trochę kodu, który zawsze był przekazywany wartościom prawdy wcześniej i nagle się nie udaje, ponieważ powinno się unikać przechodzenia przez falsey, jeśli dostępne jest bardziej niezawodne podejście. - jinglesthula


Zauważyłem, że coś prostego jest znacznie bardziej zwięzłe i czytelne osobiście.

function pick(arg, def) {
   return (typeof arg == 'undefined' ? def : arg);
}

function myFunc(x) {
  x = pick(x, 'my default');
} 

137
2018-05-21 20:18



Aktualizacja: jeśli używasz underscore.js już uważam, że jeszcze lepiej go używać _.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});. Korzystanie z globalnej przestrzeni nazw przedstawionej w tej odpowiedzi jest przez wielu uważane za złą praktykę. Możesz także rozważyć przetasowanie własnego narzędzia do tego typowego zadania (np. util.default(arg, "defaul value")) jeśli nie chcesz używać podkreślenia, ale w większości przypadków użyję podkreślenia wcześniej czy później nie ma sensu odnawiać koła. - andersand
@andersand Podoba mi się pomysł czegoś takiego util.default(arg, "defaul value"))  czy ty lub @ tj111 umiałbyś opublikować szybkie demo? - JasonDavis
Właściwie to polecam, używam go i nazywam "por", który oznacza "parametr lub" - super
Nie mów typeof arg == "undefined", zamiast tego arg mów === undefined - OsamaBinLogin
@OsamaBinLogin to, co mówisz, jest poprawne dla bieżącego JS - starszy test trwa nadal, ponieważ w niektórych przeglądarkach kiedyś było możliwe nadpisanie undefined z inną wartością, powodującą niepowodzenie testu. - Alnitak


W ECMAScript 6 faktycznie będziesz mógł napisać dokładnie to, co masz:

function read_file(file, delete_after = false) {
  // Code
}

To zostanie ustawione delete_after do false jeśli nie jest obecny lub undefined. Możesz teraz korzystać z funkcji ES6, takich jak ten, z transpilatorami takimi jak Babel.

Więcej informacji można znaleźć w artykule MDN.


54
2018-05-29 15:25



ECMAScript 6 Przypuszczam ... (poprawiłbym się sam, ale nie mogę wprowadzić zmian <6 znaków) - Zac
Oczekiwanie na przeglądarkę dostanie ECMAScript 6 - Adriano Resende
Do czego Babel to przeniesie? - harryg
@harryg: babeljs.io/repl/... - Felix Kling
Oto tabela zgodności dla ES6 kangax.github.io/compat-table/es6/#default_function_parameters Niestety ta składnia nie jest jeszcze obsługiwany. - freemanoid


Domyślne wartości parametrów

W ES6 możesz zrobić jeden z najczęstszych idiomów JavaScript odnosi się do ustawiania wartości domyślnej dla parametru funkcji. Sposób, w jaki robimy to od lat, powinien wyglądać znajomo:

function foo(x,y) {
 x = x || 11;
 y = y || 31;
 console.log( x + y );
}
foo(); // 42
foo( 5, 6 ); // 11
foo( 5 ); // 36
foo( null, 6 ); // 17

Ten wzór jest najczęściej używany, ale jest niebezpieczny, gdy przekazujemy takie wartości

foo(0, 42)
foo( 0, 42 ); // 53 <-- Oops, not 42

Czemu? Ponieważ 0 is falsy, a więc x || 11 results in 11, a nie bezpośrednio przekazane w 0. Aby rozwiązać ten problem, niektórzy ludzie zamiast tego wypiszą bardziej rozwlekle:

function foo(x,y) {
 x = (x !== undefined) ? x : 11;
 y = (y !== undefined) ? y : 31;
 console.log( x + y );
}
foo( 0, 42 ); // 42
foo( undefined, 6 ); // 17

możemy teraz sprawdzić ładną pomocną składnię dodaną jako ES6 aby usprawnić przypisanie wartości domyślnych do brakujących argumentów:

function foo(x = 11, y = 31) {
 console.log( x + y );
}

foo(); // 42
foo( 5, 6 ); // 11
foo( 0, 42 ); // 42
foo( 5 ); // 36
foo( 5, undefined ); // 36 <-- `undefined` is missing
foo( 5, null ); // 5 <-- null coerces to `0`
foo( undefined, 6 ); // 17 <-- `undefined` is missing
foo( null, 6 ); // 6 <-- null coerces to `0`

x = 11 w deklaracji funkcji jest bardziej podobne x !== undefined ? x : 11 niż dużo bardziej popularny idiom x || 11

Domyślne wyrażenia wartości

Function wartości domyślne mogą być większe niż proste wartości, takie jak 31; mogą być dowolnym ważnym wyrażeniem, nawet a function call:

function bar(val) {
 console.log( "bar called!" );
 return y + val;
}
function foo(x = y + 3, z = bar( x )) {
 console.log( x, z );
}
var y = 5;
foo(); // "bar called"
 // 8 13
foo( 10 ); // "bar called"
 // 10 15
y = 6;
foo( undefined, 10 ); // 9 10

Jak widać, domyślne wyrażenia wartości są leniwie oceniane, co oznacza, że ​​są uruchamiane tylko wtedy, gdy są potrzebne - czyli wtedy, gdy argument parametru jest pominięty lub jest niezdefiniowany.

Wyrażenie wartości domyślnej może nawet być wywołaniem funkcji śródliniowej - powszechnie nazywane wyrażeniem funkcji Natychmiastowe Wywołanie (IIFE):

function foo( x =
 (function(v){ return v + 11; })( 31 )
) {
 console.log( x );
}
foo(); // 42

18
2017-10-15 17:58





to rozwiązanie działa dla mnie w js:

function read_file(file, delete_after) {
    delete_after = delete_after || false;
    // Code
}

8
2017-11-16 11:29



Co się stanie gdy delete_after jest 0 lub null? Nie będzie działać poprawnie w tych przypadkach. - Dmitri Pavlutin
@StephanBijzitter to byłoby prawdą tylko w niektórych przypadkach. Ale jeśli chcesz ustawić tylko wartości domyślne, to nie zadziałało, ponieważ 0 lub null! === false. - Rutrus
@Rutrus: Nie rozumiem niczego, co właśnie powiedziałeś. - Stephan Bijzitter
Co powiesz na delete_after = delete_after === undefined ? false : delete_after? - aashah7


Po prostu użyj wyraźnego porównania z niezdefiniowanym.

function read_file(file, delete_after)
{
    if(delete_after === undefined) { delete_after = false; }
}

6
2017-11-16 07:34





będąc długoletnim programistą C ++ (Rookie to web development :)), kiedy po raz pierwszy natknąłem się na tę sytuację, wykonałem przypisanie parametrów w definicji funkcji, tak jak jest wspomniane w pytaniu, jak poniżej.

function myfunc(a,b=10)

Ale uważaj, że nie działa on konsekwentnie w różnych przeglądarkach. Dla mnie działało na chrome na moim pulpicie, ale nie działało na chrome na Androidzie. Opcja bezpieczniejsza, o czym wspomniano powyżej, to:

    function myfunc(a,b)
    {
    if (typeof(b)==='undefined') b = 10;
......
    }

Celem tej odpowiedzi nie jest powtarzanie tych samych rozwiązań, o czym już wspomniały inni, ale poinformowanie, że przypisanie parametru w definicji funkcji może działać w niektórych przeglądarkach, ale nie polegać na nim.


5
2018-05-19 06:40



Przypisanie w definicji funkcji również nie działa w IE 11, która jest najnowszą wersją IE dla Windows 8.1. - DiMono
Jeśli ktoś się zastanawia, function myfunc(a,b=10) jest składnia ES6, istnieją linki do tabel kompatybilności w innych odpowiedziach. - gcampbell


Jako aktualizację ... z ECMAScript 6 możesz WRESZCIE ustaw wartości domyślne w deklaracjach parametrów funkcji, takich jak:

function f (x, y = 7, z = 42) {
  return x + y + z
}

f(1) === 50

W odniesieniu do - http://es6-features.org/#DefaultParameterValues


4
2017-10-06 16:16



Ta odpowiedź nie jest przydatna, ponieważ jest duplikatem - user


Wszystkim, którzy interesują się działaniem kodu w Microsoft Edge, nie używaj wartości domyślnych w parametrach funkcji.

function read_file(file, delete_after = false) {
    #code
}

W tym przykładzie Edge rzuci błąd "Oczekiwano") ""

Aby obejść to użycie

function read_file(file, delete_after) {
  if(delete_after == undefined)
  {
    delete_after = false;
  }
  #code
}

Od 8 sierpnia 2016 r. Problem ten nadal występuje


4
2017-08-03 14:49