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.


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

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.


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.


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

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


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 .


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)


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;


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

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;

0

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

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

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


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


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.