Pytanie Jak sprawdzić "niezdefiniowany" w JavaScript? [duplikować]


To pytanie już zawiera odpowiedź:

Jaki jest najwłaściwszy sposób sprawdzenia, czy zmienna jest niezdefiniowana w JavaScript? Widziałem kilka możliwych sposobów:

if (window.myVariable)

Lub

if (typeof(myVariable) != "undefined")

Lub

if (myVariable) //This throws an error if undefined. Should this be in Try/Catch?

1875
2017-08-02 17:53


pochodzenie


Czy chcesz sprawdzić tylko  undefined, lub null także? - Nick Craver♦
Sprawdź to stackoverflow.com/questions/27509/... - Amr Badawy
@Robert - to pytanie ma akceptowaną odpowiedź, że odpowiedzi tutaj okazały się błędne - Daniel Schaffer
Widzieć: Jak sprawdzić niezdefiniowane w javascript?, i czy zmienna jest niezdefiniowana i Jak radzić sobie z "niezdefiniowanym" w javascript - Shog9♦
Ten "duplikat" dotyczy właściwości obiektu, więc niektóre odpowiedzi nie pasują do tego pytania, pytając o zmienne. - DCShannon


Odpowiedzi:


Jeśli chcesz dowiedzieć się, czy zmienna została zadeklarowana niezależnie od jej wartości, skorzystaj z in operator jest najbezpieczniejszą drogą. Rozważ ten przykład.

// global scope
var theFu; // theFu has been declared, but its value is undefined
typeof theFu; // "undefined"

Ale może to nie być zamierzony wynik w niektórych przypadkach, ponieważ zmienna lub właściwość została zadeklarowana, ale nie została zainicjowana. Użyj in operator, aby uzyskać solidniejszą kontrolę.

"theFu" in window; // true
"theFoo" in window; // false

Jeśli chcesz wiedzieć, czy zmienna nie została zadeklarowana, czy ma wartość undefined, a następnie użyj typeof operator.

if (typeof myVar != 'undefined')

The typeof operator ma pewność, że zwróci ciąg znaków. Bezpośrednie porównania z undefined są kłopotliwe jak undefined można nadpisać.

window.undefined = "omg";
"omg" == undefined // true

Jak zauważył @CMS, zostało to załatane w ECMAScript 5 wydanie undefined nie jest zapisywalny.

if (window.myVar) będą również zawierać te wartości fałszerstwa, więc nie jest to bardzo solidne:

fałszywy
0
""
NaN
zero
niezdefiniowany

Dzięki @CMS za wskazanie, że twój trzeci przypadek - if (myVariable) może również zgłosić błąd w dwóch przypadkach. Pierwszym jest, gdy zmienna nie została zdefiniowana, która wyrzuca a ReferenceError.

// abc was never declared.
if (abc) {
    // ReferenceError: abc is not defined
} 

Innym przypadkiem jest to, kiedy zmienna została zdefiniowana, ale ma funkcję gettera, która zgłasza błąd po wywołaniu. Na przykład,

// or it's a property that can throw an error
Object.defineProperty(window, "myVariable", { 
    get: function() { throw new Error("W00t?"); }, 
    set: undefined 
});
if (myVariable) {
    // Error: W00t?
}

2158
2017-08-02 17:58



@Anurag, trzeci przypadek rzuci a ReferenceError gdyby myVariable nie jest zdeklarowany... - CMS
@Anurag, nie ma za co, skoro mówisz o ES5, być może warto o tym wspomnieć undefinedjest teraz opisany jako nieprzenośny, nie można go konfigurować i jest nieprzeliczalny. Więc, window.undefined = "omg"; po prostu nie powiedzie się po cichu lub rzuci w trybie ścisłym. - CMS
Czy "typeof" może zostać zdefiniowany na nowo? - CHI Coder 007
typeof jest instrukcją języka, nie można jej przedefiniować więcej niż wtedy, gdy / else / while / for / function itp. może być. - MooGoo
undefined jest niezmienny w nowoczesne przeglądarki. Oprawa window.undefined nic nie robi. - Paul S.


Osobiście używam

myVar === undefined

Ostrzeżenie: pamiętaj, że === jest używany ponad == i to myVar było wcześniej zdeklarowany (nie określone).


nie lubię typeof myVar === "undefined". Myślę, że jest to długo zdyszane i niepotrzebne. (Mogę zrobić to samo za mniej kodu).

Teraz niektórzy ludzie będą cierpieć z bólu, gdy to przeczytają, krzycząc: "Czekaj! WAAITTT !!! undefined można na nowo zdefiniować! "

Chłodny. Wiem to. Z drugiej strony, większość zmiennych w JavaScript może zostać przedefiniowana. Czy nigdy nie użyjesz wbudowanego identyfikatora, który można przedefiniować?

Jeśli postąpisz zgodnie z tą zasadą, dobrze dla ciebie: nie jesteś hipokrytą.

Chodzi o to, że aby wykonać wiele prawdziwej pracy w JS, programiści muszą polegać na identyfikatorach, które można zdefiniować na nowo, aby były tym, czym są. Nie słyszę ludzi, którzy mówią mi, że nie powinienem używać setTimeout ponieważ ktoś może

window.setTimeout = function () {
    alert("Got you now!");
};

Dolna linia, argument "to może być przedefiniowane", aby nie używać surowca === undefined jest fałszywe.

(Jeśli nadal się boisz undefined na nowo, dlaczego ślepo integrujesz nieprzetestowany kod biblioteki z bazą kodu? Lub jeszcze prostsze: narzędzie do polerowania).


Również, jak typeof podejście, technika ta może "wykryć" niezadeklarowane zmienne:

if (window.someVar === undefined) {
    doSomething();
}

Ale obie te techniki przeciekają w ich abstrakcji. Nalegam, abyś nie używał tego ani nawet

if (typeof myVar !== "undefined") {
    doSomething();
}

Rozważać:

var iAmUndefined;

Aby złapać czy ta zmienna jest zadeklarowana, czy nie, możesz potrzebować uciekania się do in operator. (W wielu przypadkach możesz po prostu przeczytać kod O_o).

if ("myVar" in window) {
    doSomething();
}

Ale poczekaj! Jest więcej! Co się stanie, jeśli pojawi się jakaś prototypowa magia łańcuchowa ...? Teraz nawet przełożony in operator nie jest wystarczający. (Okay, skończyłem tutaj o tej części, z wyjątkiem tego, że przez 99% czasu, === undefined (i **** kaszle **** typeof) działa dobrze. Jeśli naprawdę Ci zależy, możesz przeczytać o tym temacie na własną rękę.)


888
2017-08-02 18:26



Jest to marginalnie bardziej prawdopodobne undefined można na nowo zdefiniować, tylko dlatego, że ludzie używają go do takich kontroli. Niektórzy ludzie zazwyczaj robią takie kontrole po lewej stronie: if (undefined == someVariable). Wystarczy tylko literówka, aby w milczeniu przedefiniować undefined: if (undefined = someVariable). - Tim Down
Nigdy nie piszę kodu, który ma undefined na LHS. Nawet gdybym to zrobił, fakt, że używam === zamiast == sprawia, że ​​literówka jest wyjątkowo mało prawdopodobna. Ale fakt, że == jest niepoprawny, to więcej zmartwień. W każdym razie taki błąd jest zwykle łatwy do znalezienia. Trochę jak ten błąd: typeof x == "undefned". - Thomas Eding
Jak to mogło zostać wzniesione 41 razy, po prostu nie działa. Gdyby myVar jest w rzeczywistości niezdefiniowany, kod wygeneruje błąd i łatwo go przetestować - jsfiddle.net/WcM5g Właściwym sposobem jest typeof myVar === 'undefined'. - this.lau_
@Laurent: Żart, prawda? Zakłada się, że zmienna została zadeklarowana w taki czy inny sposób, na przykład przez var słowo kluczowe lub parametr funkcji. Sprzedałbym moją duszę, zanim (celowo) napisałem kod, który próbował w dowolny sposób oddziaływać na niezadeklarowane zmienne. Pamiętaj, że niezadeklarowane i niezdefiniowane są dwie różne koncepcje w JS. - Thomas Eding
@Andy In C (i C ++), zarówno zwykłą, jak i dobrą praktyką jest odwracanie takich operandów, aby uniknąć literówek. if (NULL = myVar) nie kompiluje się i natychmiast zostaje przechwycone, podczas gdy if (myVar = NULL) tworzy błąd, który może być trudny do wyśledzenia w zależności od tego, jaki jest inny kod. Nowoczesne kompilatory powinny dać ci ostrzeżenie, ale wielu doświadczonych programistów C już wypracowało nawyk zamiany zamówienia. - GrandOpener


Za pomocą typeof to moje preferencje. Będzie działać, gdy zmienna nigdy nie została zadeklarowana, w przeciwieństwie do jakiegokolwiek porównania z == lub === operatorów lub przymusu typu przy użyciu if. (undefined, w odróżnieniu nullmoże również zostać ponownie zdefiniowany w środowiskach ECMAScript 3, co czyni go niewiarygodnym dla porównania, chociaż prawie wszystkie popularne środowiska są teraz zgodne z ECMAScript 5 lub nowszym).

if (typeof someUndeclaredVariable == "undefined") {
    // Works
}

if (someUndeclaredVariable === undefined) { 
    // Throws an error
}

149
2017-08-02 18:05



Możesz sprawdzić, czy określona zmienna globalna reprezentująca element funkcjonalności została już zdefiniowana. Na przykład kod biblioteki może chcieć sprawdzić, czy biblioteka nie została wcześniej uwzględniona. - Tim Down
"xyz" w oknie lub "xyz" w sobie są znacznie lepsze - Jamie Pate
@ JamiePate: Dla jasności, nie zgadzam się z tym 'xyz' in window jest lepszą odpowiedzią niż typeof xyz == "undefined" ponieważ testuje niewłaściwą rzecz. The in operator sprawdza istnienie nieruchomości, niezależnie od jej wartości, podczas gdy pytanie przynajmniej wydaje się pytać, jak przetestować, czy wartość zmiennej jest undefined. Być może lepszym przykładem byłby dla mnie wybór var foo; "foo" in window; to zwraca wartość true, podczas gdy foo jest zdecydowanie niezdefiniowana. - Tim Down
@JamiePate: Dlaczego jest xyz === undefined lepszy niż typeof xyz == "undefined"? Zgadzam się co do globali, ale tylko we dwójkę zalecamy sprawdzanie właściwości window. - Tim Down
W większości przypadków jest zbędny (i mniej czytelny). Jeśli wiesz, że xyz jest zadeklarowaną zmienną, po co przechodzić dodatkowe kłopoty? Sprawdzanie typów i porównywanie ciągów znaków są znacznie wolniejsze w niektórych przeglądarkach, więc jeśli wykonasz je w ciasnej pętli, stracisz trochę wydajności. jsperf.com/type-of-undefined-vs-undefined/6 - Jamie Pate


Musisz użyć typeof .

if (typeof something != "undefined") {
    // ...
}

51
2018-06-06 20:22



Lub tylko something !== undefined, zakładając, że już to zrobiłeś var undefinedz góry ostrożnie. - James
Dobrze, że dodałeś już cytaty. Jednakże, jak wspomniano w moja odpowiedź, należy pamiętać, że ścisłe porównanie (!==) nie jest konieczne w tym przypadku, ponieważ typeof zawsze zwróci ciąg znaków. - Mathias Bynens
Mathias: stosowanie tu ścisłego lub nie-ścisłego porównania jest sprawą osobistego gustu. Oba będą zawsze działać, a żadna nie jest bardziej poprawna. Może to zależeć od tego, czy domyślną pozycją jest zawsze ścisłe porównywanie, chyba że wymaga się konkretnego przymusu (na przykład zalecanego przez Crockford), czy też wolisz stosować nie ścisłe porównanie, chyba że wymagana jest ścisłość. - Tim Down


Jeśli jest niezdefiniowany, nie będzie równy łańcuchowi znaków, który zawiera znaki "niezdefiniowane", ponieważ łańcuch nie jest niezdefiniowany.

Możesz sprawdzić typ zmiennej:

if (typeof(something) != "undefined") ...

Czasami nie musisz nawet sprawdzać typu. Jeśli wartość zmiennej nie może zostać ustawiona na wartość false, gdy jest ustawiona (na przykład, jeśli jest to funkcja), można po prostu oszacować wartość zmiennej. Przykład:

if (something) {
  something(param);
}

20
2018-06-06 20:23



Nie trzeba używać nawiasów: typeof jest operatorem, a nie funkcją. - Tim Down
@Tim - Może być używany w obie strony. - Nick Craver♦
@Tim: @Nick jest poprawny. Widzieć developer.mozilla.org/en/Core_Javascript_1.5_Reference/... - Mathias Bynens
Tak, wiem o tym Prace z nawiasami, ponieważ nawiasy w tym miejscu tworzą operator grupujący, który po prostu ocenia i zwraca argument wewnątrz. Powiedziałem tylko, że są niepotrzebne. - Tim Down


Niektóre scenariusze ilustrujące wyniki różnych odpowiedzi: http://jsfiddle.net/drzaus/UVjM4/

(Należy pamiętać, że użycie var dla in testy robią różnicę w opakowaniu z zakresem)

Kod referencyjny:

(function(undefined) {
    var definedButNotInitialized;
    definedAndInitialized = 3;
    someObject = {
        firstProp: "1"
        , secondProp: false
        // , undefinedProp not defined
    }
    // var notDefined;

    var tests = [
        'definedButNotInitialized in window',
        'definedAndInitialized in window',
        'someObject.firstProp in window',
        'someObject.secondProp in window',
        'someObject.undefinedProp in window',
        'notDefined in window',

        '"definedButNotInitialized" in window',
        '"definedAndInitialized" in window',
        '"someObject.firstProp" in window',
        '"someObject.secondProp" in window',
        '"someObject.undefinedProp" in window',
        '"notDefined" in window',

        'typeof definedButNotInitialized == "undefined"',
        'typeof definedButNotInitialized === typeof undefined',
        'definedButNotInitialized === undefined',
        '! definedButNotInitialized',
        '!! definedButNotInitialized',

        'typeof definedAndInitialized == "undefined"',
        'typeof definedAndInitialized === typeof undefined',
        'definedAndInitialized === undefined',
        '! definedAndInitialized',
        '!! definedAndInitialized',

        'typeof someObject.firstProp == "undefined"',
        'typeof someObject.firstProp === typeof undefined',
        'someObject.firstProp === undefined',
        '! someObject.firstProp',
        '!! someObject.firstProp',

        'typeof someObject.secondProp == "undefined"',
        'typeof someObject.secondProp === typeof undefined',
        'someObject.secondProp === undefined',
        '! someObject.secondProp',
        '!! someObject.secondProp',

        'typeof someObject.undefinedProp == "undefined"',
        'typeof someObject.undefinedProp === typeof undefined',
        'someObject.undefinedProp === undefined',
        '! someObject.undefinedProp',
        '!! someObject.undefinedProp',

        'typeof notDefined == "undefined"',
        'typeof notDefined === typeof undefined',
        'notDefined === undefined',
        '! notDefined',
        '!! notDefined'
    ];

    var output = document.getElementById('results');
    var result = '';
    for(var t in tests) {
        if( !tests.hasOwnProperty(t) ) continue; // bleh

        try {
            result = eval(tests[t]);
        } catch(ex) {
            result = 'Exception--' + ex;
        }
        console.log(tests[t], result);
        output.innerHTML += "\n" + tests[t] + ": " + result;
    }
})();

I wyniki:

definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized == "undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized == "undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp == "undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp == "undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp == "undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined == "undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined

17
2018-01-13 15:39



zanotuj użycie undefined w opakowaniu zakresu; to nie tylko chroni przed (niecodziennym) przypadkiem "oh ale undefined można na nowo zdefiniować ", ale także" pomaga "przy zminimalizowaniu. - drzaus


if (typeof foo == 'undefined') {
 // Do something
};

Zwróć uwagę, że ścisłe porównanie (!==) nie jest konieczne w tym przypadku, ponieważ typeof zawsze zwróci ciąg znaków.


16
2018-06-06 20:26



Co to jest z średnikiem (};)? - James
@ J-P: Średnik po nawiasie zamykającym jest po prostu pustym stwierdzeniem. - Gumbo
@Gumbo, przepraszam, chciałem zapytać: "Do czego służy półkolonia?" - James
Nie spotkałem miniarki, której nie można obsłużyć if(){} bez ; ... Do których minifierów się odwołujesz? Mówisz, że tak kończysz każde inne stwierdzenie ... Myślę, że to prawda. Ale zdanie blokowe {} jest już samodzielnym stwierdzeniem. Dodawanie ; czyni technicznie dwa stwierdzenia. Syntaktycznie jest zbędny. Nawet automatyczne wstawianie średnika nie doda tam średnika ... - James
@ J-P: Myślę, że zacząłem to robić lata temu po przeczytaniu dokumentacja Packera. Packer oczekuje średników po function() {} deklaracje. Masz rację - najwyraźniej nie jest to wymagane po if oświadczenia, ale jakoś nadal uważam, że ma to sens. - Mathias Bynens


W Ten artykuł Czytam takie ramy, jak Underscore.js użyj tej funkcji:

function isUndefined(obj){
    return obj === void 0;
}

15
2017-12-19 10:42





Najbardziej niezawodny sposób, jaki znam sprawdzając undefined jest użycie void 0.

Jest to zgodne z nowszymi i starszymi przeglądarkami, podobnie i nie można ich zastąpić window.undefined może w niektórych przypadkach.

if( myVar === void 0){
    //yup it's undefined
}

9
2018-02-19 13:20



Jest to niedoceniane, a IMHO jest lepszym sposobem sprawdzenia, czy coś jest nieokreślone. - Brian M. Hunt
Absolutnie poprawne, ale wyobrażam sobie, że jeśli undefined !== void 0, prawdopodobnie masz inne poważne problemy we wspomnianym Bazie kodów. - Thomas Eding