javascript ustawia zmienną, jeśli jest niezdefiniowana

172

Wiem, że mogę przetestować zmienną javascript, a następnie zdefiniować ją, jeśli jest niezdefiniowana, ale czy nie ma sposobu na powiedzenie

var setVariable = localStorage.getItem ('value') || 0;

wydaje się dużo jaśniejszy sposób i jestem prawie pewien, że widziałem to w innych językach.

pedalpete
źródło
30
to nie jest test na „undefined”, to test na „falsey”
Alnitak
3
Pamiętaj, że localStorage.getItem()spowoduje to zgłoszenie wyjątku, jeśli użytkownik wyłączył pliki cookie (przynajmniej w Chrome), więc możesz chcieć zawrzeć go w try...catchklauzuli
urish
1
Możliwy duplikat tego, co konstruuje x = x || masz na myśli?
Michał Perłakowski

Odpowiedzi:

304

Tak, może to zrobić, ale ściśle mówiąc, przypisze wartość domyślną, jeśli pobrana wartość jest fałszywa , w przeciwieństwie do naprawdę niezdefiniowanej . Jest zatem nie tylko pasuje undefined, ale również null, false, 0, NaN, "" (ale nie "0" ).

Jeśli chcesz ustawić wartość domyślną tylko wtedy, gdy zmienna jest ściśle undefinedokreślona, ​​najbezpieczniejszym sposobem jest napisanie:

var x = (typeof x === 'undefined') ? your_default_value : x;

W nowszych przeglądarkach można bezpiecznie pisać:

var x = (x === undefined) ? your_default_value : x;

należy jednak pamiętać, że można to odwrócić w starszych przeglądarkach, w których wolno było zadeklarować zmienną o nazwie, undefinedktóra ma zdefiniowaną wartość, co spowodowało niepowodzenie testu.

Alnitak
źródło
3
Dziwię się, że ten wzorzec nie jest zawarty w większej liczbie bibliotek JS.
joemaller
czy jest wada używania var x = (x === undefined ? def_val : x);jako nieco dłuższego var x = (typeof x === 'undefined') ? def_val : x;. Czy zachowanie się różni?
Marco Pashkov
3
@marco w starszych przeglądarkach można undefinedbyło przedefiniować, co powodowało niepowodzenie testu równości.
Alnitak
@Alnitak Jakie jest najlepsze podejście, aby użyć podobnej składni do tej, której używa OP i nadal sprawdzać, czy nie ma niezdefiniowanej?
Ivo Pereira
@IvoPereira Nie możesz użyć ||podejścia w ścisłym teście dla undefined, musisz użyć jawnego testu dla undefinedwarunku.
Alnitak
26

Odpowiedź 2018 ES6 to :

return Object.is(x, undefined) ? y : x;

Jeśli zmienna x jest niezdefiniowana, zwraca zmienną y ... w przeciwnym razie, jeśli zmienna x jest zdefiniowana, zwraca zmienną x.

Sterling Bourne
źródło
4
O ile wiem, Object.isnie jest lepsze niż ===w tym przypadku. „Operator === (a także operator ==) traktuje wartości liczbowe -0 i +0 jako równe i traktuje Number.NaN jako różne od NaN.” ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) Nie ma tutaj znaczenia.
Trevor Dixon
5
Nie zgadzam się. Poznaj ich obu i używaj odpowiedniego. W szczególności użyj, Object.isjeśli oba operandy mogą być NaN.
Trevor Dixon
2
Jeśli Object.is () działa w 100% przypadków użycia, a === działa w 98% przypadków użycia, dlaczego miałbyś w ogóle ryzykować użycie ===? Na przykład: console.log (+0 === -0); // wyświetla true, while console.log (Object.is (+0, -0)); // wyświetla false - co jest lepsze? Czy ujemne 0 to to samo, co dodatnie 0? To jest pytanie, które musisz sobie zadać, ale jeśli używasz Object.is (), zawsze znasz odpowiedź. Nie są takie same, więc wynik fałszu jest poprawnym i oczekiwanym wynikiem.
Sterling Bourne
2
Konkretny kontekst tutaj jest zawsze porównywany undefined. Więc ===będzie działać w 100% przypadków, a nie tylko w 98%. Zaletą ===jest to, że jest łatwiejszy do odczytania, zwłaszcza na pierwszy rzut oka, krótszy i pozwala uniknąć niepotrzebnego wywołania metody. Osobiście używałbym tylko Object.is()wtedy, gdy sytuacja tego wymaga i wolałbym ===we wszystkich innych przypadkach.
blubberdiblub
1
Absolutnie; jeśli jesteś doświadczonym programistą. Chyba że przypadkowo zapomnisz znaku równości, w którym to przypadku debugowanie, dlaczego == gdzieś nie działa, jest czymś, czego nigdy nie życzyłbym żadnemu deweloperowi. Lepiej bezpiecznie niż żałować i zawsze używaj Object.is (), ponieważ specyfikacja została uwzględniona w specyfikacji, aby pomóc programistom w pisaniu mniej błędnego kodu.
Sterling Bourne
7

Musiałem „ustawić zmienną, jeśli jest niezdefiniowana” w kilku miejscach. Utworzyłem funkcję za pomocą odpowiedzi @Alnitak. Mam nadzieję, że to komuś pomoże.

function setDefaultVal(value, defaultValue){
   return (value === undefined) ? defaultValue : value;
}  

Stosowanie:

hasPoints = setDefaultVal(this.hasPoints, true);
Mcestone
źródło
6

Bardziej logiczne wydaje się sprawdzenie typeofzamiast undefined? Zakładam, że oczekujesz liczby, ustawiając zmienną na 0undefined:

var getVariable = localStorage.getItem('value');
var setVariable = (typeof getVariable == 'number') ? getVariable : 0;

W tym przypadku, jeśli getVariablenie jest liczbą (ciągiem, obiektem, czymkolwiek), ustawiana jest wartość setVariable0

Bruno
źródło
5

Odpowiedź ES2020

Za pomocą zerowego operatora łączenia można ustawić wartość domyślną, jeśli valuejest równa zeru lub nieokreślona.

const setVariable = localStorage.getItem('value') ?? 0;

Należy jednak pamiętać, że nullish coalescing operator nie zwraca wartości domyślnej dla innych typów fałszywych wartości, takich jak 0i ''.

Zwróć uwagę, że obsługa przeglądarki przez operatora jest ograniczona. Według danych caniuse obsługiwanych jest tylko 48,34% przeglądarek (stan na kwiecień 2020). Obsługa Node.js została dodana w wersji 14 .

Wentjun
źródło
2

Jeśli jesteś fanem FP ( programowania funkcjonalnego ), Ramda ma fajną funkcję pomocniczą o nazwie defaultTo :

stosowanie:

const result = defaultTo(30)(value)

Jest to bardziej przydatne w przypadku undefinedwartości logicznych:

const result2 = defaultTo(false)(dashboard.someValue)

Damian Green
źródło
1
to jest dokładnie const result = value || 30;, z wyjątkiem używania funkcji pośredniej i +1000 bajtów lib
Adelin
1
@Adelin nie jest prawdą, obsługuje również fałsz dla typów logicznych. Jeśli już używasz tej biblioteki (tak jak ja), to jest całkiem przydatna i zwięzła
Damian Green
1

var setVariable = (typeof localStorage.getItem('value') !== 'undefined' && localStorage.getItem('value')) || 0;

Zikes
źródło
Nie przypisze również 0, jeśli localStorage.getItem('value'))zwrócifalse
Karl Adler
1

Dzisiaj również wpadłem na ten scenariusz, w którym nie chciałem, aby zero zostało nadpisane dla kilku wartości. Mamy plik z kilkoma typowymi metodami narzędziowymi dla takich scenariuszy. Oto, co dodałem, aby poradzić sobie ze scenariuszem i być elastycznym.

function getIfNotSet(value, newValue, overwriteNull, overwriteZero) {
    if (typeof (value) === 'undefined') {
        return newValue;
    } else if (value === null && overwriteNull === true) {
        return newValue;
    } else if (value === 0 && overwriteZero === true) {
        return newValue;
    } else {
        return value;
    }
}

Następnie można go wywołać z dwoma ostatnimi parametrami, które są opcjonalne, jeśli chcę ustawić tylko niezdefiniowane wartości lub nadpisać wartości null lub 0. Oto przykład wywołania, które ustawi identyfikator na -1, jeśli identyfikator jest niezdefiniowany lub pusty, ale nie nadpisze wartości 0.

data.ID = Util.getIfNotSet(data.ID, -1, true);
Mark Seefeldt
źródło
1

W dzisiejszych czasach możesz zrobić swoje podejście za pomocą JS:

// Your variable is null
// or '', 0, false, undefined
let x = null;

// Set default value
x = x || 'default value';

console.log(x); // default value

Twój przykład BĘDZIE działał:

const setVariable = localStorage.getItem('value') || 0;
tarkh
źródło
0

Działa nawet, jeśli wartość domyślna jest wartością logiczną:

var setVariable = ( (b = 0) => b )( localStorage.getItem('value') );
Tsz Lam Yau
źródło
0

Wydaje mi się, że przy obecnych implementacjach javascript,

var [result='default']=[possiblyUndefinedValue]

to dobry sposób na zrobienie tego (za pomocą dekonstrukcji obiektów).

TS
źródło
0

Logiczne przypisanie zerowe, rozwiązanie ES2020 +

Nowi operatorzy są obecnie dodawane do przeglądarek ??=, ||=oraz &&=. Ten post skupi się na ??=.

Sprawdza, czy lewa strona jest niezdefiniowana lub zerowa, zwarcie, jeśli jest już zdefiniowane. Jeśli nie, prawa strona jest przypisywana do zmiennej lewej strony.

Porównanie metod

// Using ??=
name ??= "Dave"

// Previously, ES2020
name = name ?? "Dave"

// Before that (not equivalent, but commonly used)
name = name || "Dave" // name ||= "Dave"

Podstawowe przykłady

let a          // undefined
let b = null
let c = false

a ??= true  // true
b ??= true  // true
c ??= true  // false

// Equivalent to
a = a ?? true

Przykłady obiektów / tablic

let x = ["foo"]
let y = { foo: "fizz" }

x[0] ??= "bar"  // "foo"
x[1] ??= "bar"  // "bar"

y.foo ??= "buzz"  // "fizz"
y.bar ??= "buzz"  // "buzz"

x  // Array [ "foo", "bar" ]
y  // Object { foo: "fizz", bar: "buzz" }

?? = Obsługa przeglądarek, lipiec 2020 r. - 0,03%

?? = Dokumentacja Mozilli

|| = Dokumentacja Mozilli

&& = Dokumentacja Mozilli

Gibolt
źródło
Czy naprawdę dobrym pomysłem jest skopiowanie tej odpowiedzi na dwa inne pytania ( Zastąp wartość, jeśli jest pusta lub nieokreślona w JavaScript i Czy w JavaScript istnieje operator „łączący wartość null”? )? Czy nie byłoby lepiej, aby VTC jako duplikat lub link do powiązanych pytań w komentarzach?
user4642212
Wszystkie pytania są nieco inne; jako takie są odpowiedzi. Przykłady są spójne, aby na pierwszy rzut oka ulepszyć kontekst wbudowany. Prawdopodobnie mógł link, aby uzyskać więcej szczegółów, ale wymagałby dodatkowego przeskoku, który mógłby spowodować, że ludzie
pominęliby