Wykrywanie niezdefiniowanej właściwości obiektu

2838

Jaki jest najlepszy sposób sprawdzenia, czy właściwość obiektu w JavaScript jest undefined?

Matt Sheppard
źródło

Odpowiedzi:

2679

Typowym sposobem sprawdzenia, czy wartość właściwości jest wartością specjalną undefined, jest:

if(o.myProperty === undefined) {
  alert("myProperty value is the special value `undefined`");
}

Aby sprawdzić, czy obiekt tak naprawdę nie ma takiej właściwości, dlatego undefineddomyślnie wróci , gdy spróbujesz uzyskać do niego dostęp:

if(!o.hasOwnProperty('myProperty')) {
  alert("myProperty does not exist");
}

Aby sprawdzić, czy wartość związana z identyfikatorem jest wartość specjalny undefined, lub jeśli identyfikator nie został uznany. Uwaga: ta metoda jest jedynym sposobem odwoływania się do niezadeklarowanego (uwaga: różniącego się od posiadania wartości undefined) identyfikatora bez wczesnego błędu:

if(typeof myVariable === 'undefined') {
  alert('myVariable is either the special value `undefined`, or it has not been declared');
}

W wersjach JavaScript wcześniejszych niż ECMAScript 5 właściwość o nazwie „undefined” w obiekcie globalnym była zapisywalna, a zatem proste sprawdzenie foo === undefinedmoże zachowywać się nieoczekiwanie, jeśli zostanie przypadkowo przedefiniowane. W nowoczesnym JavaScript właściwość jest tylko do odczytu.

Jednak we współczesnym JavaScript JavaScript słowo „niezdefiniowany” nie jest słowem kluczowym, dlatego zmienne w funkcjach można nazwać „niezdefiniowanymi” i zasłaniać globalną właściwość.

Jeśli martwi Cię ten (mało prawdopodobny) przypadek krawędzi, możesz użyć operatora pustki, aby uzyskać undefinedsamą wartość specjalną :

if(myVariable === void 0) {
  alert("myVariable is the special value `undefined`");
}
Ry-
źródło
9
jeśli coś ma wartość NULL, jest ono zdefiniowane (jako NULL), ale można również skoniugować kontrole zbyt. Irytującym szczegółem powyższego kodu jest to, że nie możesz zdefiniować funkcji, która by to sprawdzić, możesz zdefiniować funkcję ... ale spróbuj z niej skorzystać.
neu-rah
5
@ neu-rah dlaczego nie możesz napisać funkcji? dlaczego coś takiego nie działa? Wydaje mi się, że to działa. Czy jest przypadek, którego nie rozważam? jsfiddle.net/djH9N/6
Zack
7
@Zack W testach dla isNullorUndefined nie uwzględniono przypadku, w którym wywoływane jest isNullOrUndefined (f) if jest niezadeklarowane (tzn. Gdy nie ma deklaracji „var f”).
pnkfelix
109
Blah, tysiące głosów teraz. To najgorszy możliwy sposób. Mam nadzieję, że przechodnie zobaczą ten komentarz i postanowią sprawdzić… hm… inne odpowiedzi.
Ry-
17
Możesz po prostu użyć obj !== undefinedteraz. undefinedKiedyś można go było modyfikować, tak undefined = 1234jak w przypadku interesujących wyników. Ale po Ecmascript 5 nie można już zapisywać, więc możemy użyć prostszej wersji. codereadability.com/how-to-check-for-undefined-in-javascript
Bruno Buccolo
899

Uważam, że istnieje wiele niepoprawnych odpowiedzi na ten temat. Wbrew powszechnemu przekonaniu „niezdefiniowany” nie jest jest słowem kluczowym w JavaScript i może mieć przypisaną wartość.

Poprawny kod

Najbardziej niezawodny sposób na wykonanie tego testu to:

if (typeof myVar === "undefined")

To zawsze zwraca poprawny wynik, a nawet radzi sobie z sytuacją, w której myVar nie jest zadeklarowany.

Kod zdegenerowany. NIE UŻYWAJ.

var undefined = false;  // Shockingly, this is completely legal!
if (myVar === undefined) {
    alert("You have been misled. Run away!");
}

Dodatkowo myVar === undefinedspowoduje błąd w sytuacji, gdy myVar nie jest zgłoszony.

MarkPflug
źródło
133
+1 za zauważenie, że myVar === undefined spowoduje błąd, jeśli myVar nie zostanie zadeklarowane
Enrique
73
Znajduję tutaj pierwsze uzasadnienie, by nie używać === undefinedoszołomienia. Tak, możesz przypisać do undefined, ale nie ma uzasadnionego powodu, aby to zrobić, i można przewidzieć, że może to spowodować uszkodzenie kodu. W C możesz #define true false, aw Pythonie możesz przypisać Truei False, ale ludzie nie czują potrzeby projektowania swojego kodu w tych językach w taki sposób, aby zabezpieczyć się przed możliwością celowego sabotowania własnego środowiska w innym miejscu kodu . Dlaczego undefinedwarto tutaj przypisać nawet wartość?
Mark Amery
19
oprócz komentarzy Marks nie otrzymuję tego: „myVar === undefined spowoduje błąd w sytuacji, gdy myVar nie jest zadeklarowany”. - dlaczego to takie złe? Dlaczego nie chcę mieć błędu, jeśli odwołuję się do niezadeklarowanych zmiennych?
eis
5
Pamiętaj również, że zawsze możesz zrobić, void 0aby uzyskać wartość, która undefinedwskazuje. Więc możesz to zrobić if (myVar === void 0). 0nie jest wyjątkowy, można dosłownie umieścić dowolny wyraz tam.
Claudiu
28
W nowoczesnych przeglądarkach (FF4 +, IE9 +, Chrome nieznane) modyfikacja nie jest już możliwa undefined. MDN: undefined
user247702
228

Pomimo tego, że jest gorąco polecany przez wiele innych odpowiedzi tutaj, typeof jest złym wyborem . Nigdy nie należy go używać do sprawdzania, czy zmienne mają wartość undefined, ponieważ działa to jako łączone sprawdzenie wartości undefinedi tego, czy zmienna istnieje. W zdecydowanej większości przypadków wiesz, kiedy istnieje zmienna, i typeofpo prostu wprowadzasz możliwość cichej awarii, jeśli popełnisz literówkę w nazwie zmiennej lub w literale ciągu 'undefined'.

var snapshot = …;

if (typeof snaposhot === 'undefined') {
    //         ^
    // misspelled¹ – this will never run, but it won’t throw an error!
}
var foo = …;

if (typeof foo === 'undefned') {
    //                   ^
    // misspelled – this will never run, but it won’t throw an error!
}

Tak więc, chyba że wykonujesz wykrywanie typeof module !== 'undefined'funkcji² , gdzie nie ma pewności, czy dana nazwa będzie objęta zakresem (np. Sprawdzanie jako krok w kodzie specyficznym dla środowiska CommonJS), typeofjest szkodliwym wyborem, gdy jest używana w zmiennej, a poprawną opcją jest aby bezpośrednio porównać wartość:

var foo = …;

if (foo === undefined) {
    
}

Niektóre typowe nieporozumienia na ten temat obejmują:

  • że odczyt „niezainicjowanej” zmiennej ( var foo) lub parametru ( function bar(foo) { … }zwanego as bar()) zakończy się niepowodzeniem. To po prostu nieprawda - zmienne bez wyraźnej inicjalizacji i parametry, którym nie podano wartości, zawsze stają się undefinedi zawsze mają zakres.

  • które undefinedmożna zastąpić. Jest o wiele więcej. undefinednie jest słowem kluczowym w JavaScript. Zamiast tego jest to właściwość obiektu globalnego o wartości Niezdefiniowana. Jednak od wersji ES5 ta właściwość jest tylko do odczytu i nie można jej konfigurować . Żadna nowoczesna przeglądarka nie pozwoli na zmianę undefinedwłaściwości, a od 2017 r. Ma to miejsce od dłuższego czasu. Brak trybu ścisłego również nie wpływa na undefinedzachowanie - po prostu powoduje, że wyrażenia takie jak „ undefined = 5nic nie rób” zamiast rzucać. Ponieważ nie jest to słowo kluczowe, możesz zadeklarować zmienne o nazwie undefined, a zmienne te można zmienić, tworząc ten kiedyś powszechny wzorzec:

    (function (undefined) {
        // …
    })()

    bardziej niebezpieczne niż używanie globalnego undefined. Jeśli musisz być zgodny undefinedz ES3, zamień na void 0- nie uciekaj się typeof. ( voidzawsze był jednoargumentowym operatorem, który ocenia wartość niezdefiniowaną dla dowolnego argumentu).

Ponieważ zmienne działają na przeszkodzie, nadszedł czas, aby odpowiedzieć na rzeczywiste pytanie: właściwości obiektu. Nie ma powodu, aby kiedykolwiek używać typeofwłaściwości obiektu. Wcześniejszy wyjątek dotyczący wykrywania funkcji nie ma tutaj zastosowania -typeof ma on tylko specjalne zachowanie względem zmiennych, a wyrażenia odwołujące się do właściwości obiektu nie są zmiennymi.

To:

if (typeof foo.bar === 'undefined') {
    
}

jest zawsze dokładnie równoważne z tym3:

if (foo.bar === undefined) {
    
}

i biorąc pod uwagę powyższą poradę, aby uniknąć mylenia czytelników co do tego, dlaczego używasz typeof, ponieważ najbardziej sensowne jest użycie ===do sprawdzenia równości, ponieważ można ją ponownie sprawdzić, sprawdzając wartość zmiennej później, i ponieważ jest to po prostu zwykłe wygląda lepiej, zawsze należy również użyć === undefined³ tutaj .

Jeśli chodzi o właściwości obiektu, należy wziąć pod uwagę jeszcze to, czy naprawdę chcesz to sprawdzić undefined. Dana nazwa właściwości może być nieobecna na obiekcie (generując wartość undefinedpodczas odczytu), być obecna na samym obiekcie z wartością undefined, występować na prototypie obiektu z wartością undefinedlub być obecna na dowolnym z tych, które nie mają undefinedwartości. 'key' in objpowie ci, czy klucz znajduje się gdzieś w łańcuchu prototypowym obiektu, i Object.prototype.hasOwnProperty.call(obj, 'key')powie, czy jest bezpośrednio na obiekcie. Nie będę jednak szczegółowo omawiał odpowiedzi na temat prototypów i używania obiektów jako map z kluczem łańcuchowym, ponieważ ma to na celu przede wszystkim przeciwdziałanie wszelkim złym radom w innych odpowiedziach, niezależnie od możliwych interpretacji pierwotnego pytania. Czytaj dalejprototypy obiektów na MDN, aby uzyskać więcej!

¹ niezwykły wybór przykładowej nazwy zmiennej? to jest naprawdę martwy kod z rozszerzenia NoScript dla Firefoksa.
² nie zakładaj jednak, że nie wiadomo, co jest w zasięgu, jest ogólnie w porządku. dodatkowa wrażliwość spowodowana nadużyciem zakresu dynamicznego: Projekt Zero 1225
³ ponownie przyjmuje środowisko ES5 + i undefinedodnosi się do undefinedwłaściwości obiektu globalnego. zastąpić void 0inaczej.

Ry-
źródło
@BenjaminGruenbaum Prawda, ale całkowicie myląca. Każdy inny niż domyślny kontekst może zdefiniować własny undefined, ukrywając domyślny. Który dla większości praktycznych celów ma taki sam efekt jak nadpisanie go.
blgt
23
@blgt To jest paranoiczne i nie ma znaczenia dla niczego praktycznego. Każdy kontekst może zastąpić plik console.log, ponownie zdefiniować metody prototypowe Array, a nawet zastąpić przechwytywanie Function.prototype.call` i modyfikowanie za każdym razem, gdy wywołujesz funkcję w JavaScript. Ochrona przed tym jest bardzo paranoiczna i raczej głupia. Jak powiedziałem (i minitech), możesz użyć void 0do porównania z nieokreślonym, ale znowu - to głupie i przesadne.
Benjamin Gruenbaum,
19
Chciałbym mieć więcej niż jeden głos do wyrażenia opinii. To jest najbardziej poprawna odpowiedź. Naprawdę chcę przestać widzieć typeof something === "undefined") w kodzie.
Simon Baumgardt-Wellander
@BenjaminGruenbaum Dla leniwych programistów void 0jest (raz) zarówno krótszy, jak i bezpieczniejszy! To zwycięstwo w mojej książce.
wizzwizz4 11.04.18
4
To naprawdę powinna być zaakceptowana odpowiedź. Jest to najbardziej dokładny i aktualny.
Patrick Michaelsen,
161

W JavaScript jest null i jest niezdefiniowany . Mają różne znaczenia.

  • niezdefiniowana oznacza, że ​​wartość zmiennej nie została zdefiniowana; nie wiadomo, jaka jest wartość.
  • null oznacza, że ​​wartość zmiennej jest zdefiniowana i ustawiona na null (nie ma wartości).

Marijn Haverbeke w swojej bezpłatnej książce online „ Eloquent JavaScript ” (moje podkreślenie):

Istnieje również podobna wartość, null, której znaczenie to „ta wartość jest zdefiniowana, ale nie ma wartości”. Różnica w znaczeniu między niezdefiniowanym a zerowym jest głównie akademicka i zwykle niezbyt interesująca. W praktycznych programach często konieczne jest sprawdzenie, czy coś „ma wartość”. W takich przypadkach można użyć wyrażenia coś == niezdefiniowana, ponieważ nawet jeśli nie są one dokładnie tą samą wartością, wartość null == niezdefiniowana da wartość true.

Myślę, że najlepszym sposobem sprawdzenia, czy coś jest niezdefiniowane, byłoby:

if (something == undefined)

Mam nadzieję że to pomoże!

Edycja: w odpowiedzi na edycję właściwości obiektu powinny działać w ten sam sposób.

var person = {
    name: "John",
    age: 28,
    sex: "male"
};

alert(person.name); // "John"
alert(person.fakeVariable); // undefined
Pandincus
źródło
42
if (coś == niezdefiniowany) lepiej napisać tak, jakby (coś === niezdefiniowany)
Sebastian Rittau
59
Należy zauważyć, że nie jest to całkowicie bezpieczne. undefinedjest tylko zmienną, którą użytkownik może przypisać ponownie: pisanie undefined = 'a';spowoduje, że kod przestanie robić to, co myślisz. Korzystanie typeofjest lepsze i działa również w przypadku zmiennych (nie tylko właściwości), które nie zostały zadeklarowane.
Gabe Moothart
7
jeśli coś jest niezdefiniowaną zmienną globalną, (coś == niezdefiniowana) wywołuje błąd javascript.
Morgan Cheng
8
Problem polega na tym, że jeśli var a = null, to a == undefined zwraca wartość true, nawet jeśli a jest z całą pewnością zdefiniowane.
Andrew
6
Ta interpretacja komentarza „Elokwentny Javascript” jest wsteczna . Jeśli naprawdę chcesz po prostu sprawdzić, czy jest niezdefiniowany, sugerowany kod nie będzie działał (wykryje również zdefiniowany warunek, ale nie przyjęto jeszcze żadnej wartości [ienull]). Sugerowany kod „if (coś == niezdefiniowany) ...” sprawdza zarówno niezdefiniowany, jak i zerowy (brak ustawionej wartości), tzn. Jest interpretowany jako „if ((coś jest niezdefiniowane) LUB (coś jest puste)) ...” Autor mówi, że często tak naprawdę naprawdę chcesz sprawdzić, czy jest zarówno niezdefiniowany, jak i zerowy.
Chuck Kollars
125

Co to znaczy: „niezdefiniowana właściwość obiektu” ?

W rzeczywistości może to oznaczać dwie zupełnie różne rzeczy! Po pierwsze, może to oznaczać właściwość, która nigdy nie została zdefiniowana w obiekcie, a po drugie, może oznaczać właściwość o nieokreślonej wartości . Spójrzmy na ten kod:

var o = { a: undefined }

Jest o.aniezdefiniowany? Tak! Jego wartość jest nieokreślona. Jest o.bniezdefiniowany? Pewnie! W ogóle nie ma właściwości „b”! OK, zobacz teraz, jak zachowują się różne podejścia w obu sytuacjach:

typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false

Możemy to wyraźnie zobaczyć typeof obj.prop == 'undefined'i obj.prop === undefinedsą równoważne i nie rozróżniają tych różnych sytuacji. I 'prop' in objmoże wykryć sytuację, w której właściwość nie została w ogóle zdefiniowana i nie zwraca uwagi na wartość właściwości, która może być niezdefiniowana.

Co więc zrobić?

1) Chcesz wiedzieć, czy właściwość jest niezdefiniowana na podstawie pierwszego lub drugiego znaczenia (najbardziej typowa sytuacja).

obj.prop === undefined // IMHO, see "final fight" below

2) Chcesz tylko wiedzieć, czy obiekt ma jakąś właściwość i nie przejmuj się jego wartością.

'prop' in obj

Uwagi:

  • Nie można jednocześnie sprawdzić obiektu i jego właściwości. Na przykład to x.a === undefinedlub to typeof x.a == 'undefined'rośnie, ReferenceError: x is not definedjeśli x nie jest zdefiniowane.
  • Zmienna undefinedjest zmienną globalną (tak więc faktycznie znajduje się window.undefinedw przeglądarkach). Jest obsługiwany od ECMAScript 1st Edition, a od ECMAScript 5 jest tylko do odczytu . Dlatego we współczesnych przeglądarkach nie można tego zmienić na prawdziwe, ponieważ wielu autorów lubi nas straszyć, ale nadal dotyczy to starszych przeglądarek.

Ostateczna walka: obj.prop === undefinedvstypeof obj.prop == 'undefined'

Plusy obj.prop === undefined:

  • Jest nieco krótszy i wygląda trochę ładniej
  • Silnik JavaScript wyświetli błąd, jeśli popełnisz błąd undefined

Wady obj.prop === undefined:

  • undefined można zastąpić w starych przeglądarkach

Plusy typeof obj.prop == 'undefined':

  • To jest naprawdę uniwersalne! Działa w nowych i starych przeglądarkach.

Wady typeof obj.prop == 'undefined':

  • 'undefned'( niepoprawnie napisane ) tutaj jest tylko ciągiem ciągłym, więc silnik JavaScript nie może ci pomóc, jeśli źle napisałeś tak jak przed chwilą.

Aktualizacja (dla JavaScript po stronie serwera):

Node.js obsługuje zmienną globalną undefinedjako global.undefined(można jej również używać bez prefiksu „globalnego”). Nie wiem o innych implementacjach JavaScript po stronie serwera.

Konstantin Smolianin
źródło
@Bergi dziękuję za komentarz. Poprawiłem swoją odpowiedź. W mojej obronie mogę powiedzieć, że obecnie (od v.10.10.18) oficjalna dokumentacja Node.js nic nie mówi o undefinedczłonkostwie global. Również ani console.log(global);nie for (var key in global) { ... }jest niezdefiniowany jako członek globalny . Ale test jak 'undefined' in globalpokazuje odwrotnie.
Konstantin Smolyanin,
4
Nie potrzebował dodatkowej dokumentacji, ponieważ znajduje się w specyfikacji EcmaScript , która również mówi, że [[Enumerable]]to nieprawda :-)
Bergi,
5
Jeśli chodzi o Minuses of typeof obj.prop == 'undefined'to, można tego uniknąć, pisząc jako typeof obj.prop == typeof undefined. Daje to również bardzo ładną symetrię.
hlovdal
3
@hlovdal: To jest całkowicie bezcelowe vs. obj.prop === undefined.
Ry-
1
Kiedy jesteśmy wierni nagłówkowi pytania Wykrywanie niezdefiniowanej właściwości” , nie jest to zgodne z (innym i znacznie łatwiejszym) pytaniem w pierwszym zdaniu („sprawdź, jeśli nieokreślona ...”), odpowiadasz if ('foo' in o)… twoja odpowiedź jest prawdziwa pierwsza poprawna odpowiedź tutaj. Prawie wszyscy inni po prostu odpowiadają na to zdanie.
Frank Nocke,
70

Problem sprowadza się do trzech przypadków:

  1. Obiekt ma właściwość, a jego wartość nie undefined.
  2. Obiekt ma właściwość, a jego wartość to undefined.
  3. Obiekt nie ma właściwości.

To mówi nam coś, co uważam za ważne:

Istnieje różnica między niezdefiniowanym elementem a zdefiniowanym elementem o nieokreślonej wartości.

Ale niestety typeof obj.foonie mówi nam, który z trzech przypadków mamy. Możemy jednak połączyć to z, "foo" in objaby rozróżnić przypadki.

                               |  typeof obj.x === 'undefined' | !("x" in obj)
1.                     { x:1 } |  false                        | false
2.    { x : (function(){})() } |  true                         | false
3.                          {} |  true                         | true

Warto zauważyć, że testy te są takie same dla nullwpisów

                               |  typeof obj.x === 'undefined' | !("x" in obj)
                    { x:null } |  false                        | false

Twierdzę, że w niektórych przypadkach bardziej sensowne (i jest jaśniejsze) jest sprawdzenie, czy właściwość istnieje, niż sprawdzenie, czy jest ona niezdefiniowana, a jedynym przypadkiem, w którym ta kontrola będzie inna, jest przypadek 2, rzadki przypadek rzeczywisty wpis w obiekcie o nieokreślonej wartości.

Na przykład: Właśnie refaktoryzowałem pęk kodu, który zawierał kilka sprawdzeń, czy obiekt ma daną właściwość.

if( typeof blob.x != 'undefined' ) {  fn(blob.x); }

Co było wyraźniejsze, gdy napisano bez czeku na niezdefiniowane.

if( "x" in blob ) { fn(blob.x); }

Ale jak już wspomniano, nie są one dokładnie takie same (ale są wystarczająco dobre dla moich potrzeb).

Michael Anderson
źródło
10
Cześć Michał. Świetna sugestia i myślę, że to czyni rzeczy czystszymi. Jedną z problemów, które znalazłem, jest jednak podczas korzystania z! operator z „in”. Musisz powiedzieć if (!("x" in blob)) {}z nawiasami wokół, ponieważ! operator ma pierwszeństwo przed „w”. Mam nadzieję, że komuś pomoże.
Simon East
Przykro mi Michael, ale w świetle pierwotnego pytania jest to niepoprawne lub przynajmniej wprowadzające w błąd. „in” nie jest wystarczającym sposobem sprawdzenia, czy właściwość obiektu ma niezdefiniowany typ. Aby uzyskać dowód, zobacz to skrzypce: jsfiddle.net/CsLKJ/4
tex
2
Te dwie części kodu robią coś innego! Rozważ i przedmiot podane przez a = {b: undefined}; wtedy typeof a.b === typeof a.c === 'undefined'ale 'b' in ai !('c' in a).
mgol
3
+1. OP nie wyjaśnia, czy właściwość istnieje i czy wartość jest niezdefiniowana , czy też sama właściwość jest niezdefiniowana (tj. Nie istnieje).
RobG
Sugerowałbym zmianę punktu (2.) w pierwszej tabeli { x : undefined }lub przynajmniej dodanie go jako kolejnej alternatywy dla (2.) w tabeli - musiałem pomyśleć przez chwilę, aby zdać sobie sprawę, że punkt (2.) ocenia undefined(chociaż wspominasz o tym później).
mucaho
46
if ( typeof( something ) == "undefined") 

To działało dla mnie, podczas gdy inni nie.

Kevin
źródło
47
pareny są niepotrzebne, ponieważ typof jest operatorem
aehlke,
12
Ale wyjaśniają, co jest sprawdzane. W przeciwnym razie można to odczytać jako typeof (something == "undefined").
Abhi Beckert,
Jeśli potrzebujesz nawiasów, powinieneś nauczyć się pierwszeństwa operatora w JS: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ian
11
Nawiasy są przydatne właśnie dlatego, że NIE musisz uczyć się pierwszeństwa operatora w JS, ani nie musisz spekulować, czy przyszli programiści konserwacji będą musieli nauczyć się pierwszeństwa operatorów w JS.
DaveWalley
27
Nawiasy są przydatne do wyjaśnienia rzeczy. Ale w tym przypadku po prostu sprawiają, że operator wygląda jak funkcja. Bez wątpienia wyjaśnia to zamiar programisty. Ale jeśli nie masz pewności co do pierwszeństwa operatora, powinieneś raczej napisać to jako (typeof something) === "undefined".
Robert
42

Nie jestem pewien, gdzie pochodzenie korzystania ===ze typeofpochodzi, jak i konwencji widzę to stosowane w wielu bibliotekach, ale operator typeof zwraca ciągiem znaków, a wiemy, że góry, więc dlaczego chcesz także rodzaj też to sprawdzić?

typeof x;                      // some string literal "string", "object", "undefined"
if (typeof x === "string") {   // === is redundant because we already know typeof returns a string literal
if (typeof x == "string") {    // sufficient
Eric
źródło
Świetna uwaga, Eric. Czy istnieje także efekt wydajności związany ze sprawdzaniem typu?
Simon East
5
@ Simon: wręcz przeciwnie - można spodziewać się niewielkiego spadku wydajności w wyniku uniknięcia przymusu w przypadku „===”. Szybki i brudny test wykazał, że „===” jest o 5% szybszy niż „==” pod FF5.0.1
Antony Hatchkins,
5
Dokładniejszy test wykazał, że pod FF, IE i Chrome „==” jest mniej więcej szybszy niż „===” (5-10%), a Opera nie robi żadnej różnicy: jsperf.com/triple- equals-vs-dwukrotnie-equals / 6
Antony Hatchkins
3
Używanie ==nadal wymaga co najmniej sprawdzenia typu - interpreter nie może porównać dwóch operandów, nie znając najpierw ich typu.
Alnitak,
7
==jest o jedną postać mniej niż ===:)
svidgen
25

Przeniesienie odpowiedzi z powiązanego pytania Jak sprawdzić, czy w JavaScript jest „niezdefiniowany”?

Specyficzne dla tego pytania, patrz przypadki testowe z someObject.<whatever>.


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

(Należy pamiętać, że użycie vardo intestów robi różnicę, gdy znajduje się w opakowaniu z lunetą)

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
drzaus
źródło
21

Jeśli zrobisz

if (myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

zakończy się niepowodzeniem, gdy zmienna myvarnie istnieje, ponieważ myvar nie jest zdefiniowany, więc skrypt jest zepsuty, a test nie ma wpływu.

Ponieważ obiekt okna ma zasięg globalny (obiekt domyślny) poza funkcją, deklaracja zostanie „dołączona” do obiektu okna.

Na przykład:

var myvar = 'test';

Zmienna globalna myvar jest taka sama jak window.myvar lub window ['myvar']

Aby uniknąć błędów w testowaniu, gdy istnieje zmienna globalna, lepiej użyć:

if(window.myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

Pytanie, czy zmienna naprawdę istnieje, nie ma znaczenia, jej wartość jest niepoprawna. W przeciwnym razie głupio jest inicjalizować zmienne z niezdefiniowanym i lepiej jest użyć wartości false do inicjalizacji. Kiedy wiesz, że wszystkie deklarowane przez ciebie zmienne są inicjalizowane wartością false, możesz po prostu sprawdzić jego typ lub polegać na !window.myvarsprawdzeniu, czy ma on prawidłową / prawidłową wartość. Nawet jeśli zmienna nie jest zdefiniowana, to !window.myvarjest taka sama dla myvar = undefinedlub myvar = falselub myvar = 0.

Gdy oczekujesz określonego typu, sprawdź typ zmiennej. Aby przyspieszyć testowanie stanu, lepiej:

if( !window.myvar || typeof window.myvar != 'string' )
{
    alert('var does not exists or is not type of string');
}

Gdy pierwszy i prosty warunek jest spełniony, tłumacz pomija kolejne testy.

Zawsze lepiej jest użyć instancji / obiektu zmiennej, aby sprawdzić, czy uzyskała prawidłową wartość. Jest bardziej stabilny i stanowi lepszy sposób programowania.

(y)

Codebeat
źródło
19

Nie widziałem (mam nadzieję, że nie tęskniłem) nikogo sprawdzającego obiekt przed nieruchomością. Jest to więc najkrótszy i najskuteczniejszy (choć niekoniecznie najbardziej wyraźny):

if (obj && obj.prop) {
  // Do something;
}

Jeśli obiekt obj lub obj.prop jest niezdefiniowany, null lub „falsy”, instrukcja if nie wykona bloku kodu. Jest to zwykle pożądane zachowanie w większości instrukcji bloków kodu (w JavaScript).

Joe Johnson
źródło
2
Jeśli chcesz wiedzieć, dlaczego to działa: javascript: Logika Operatorzy i truthy / falsy
mb21
jeśli chcesz przypisać właściwość do zmiennej, jeśli jest zdefiniowana, a nie null i nie falsey, w przeciwnym razie użyj wartości domyślnej, możesz użyć: var x = obj && obj.prop || 'default';
Stijn de Witt
Uważam, że chodzi o jawne sprawdzenie w stosunku do niezdefiniowanego. Twój stan sprawdza się względem wszystkich fałszywych wartości JS.
NikoKyriakid
15

W artykule Exploring the Abyss of Null and Undefined in JavaScript przeczytałem, że frameworki takie jak Underscore.js używają tej funkcji:

function isUndefined(obj){
    return obj === void 0;
}
Marthijn
źródło
3
void 0to tylko krótki sposób pisania undefined(ponieważ to właśnie pustka, po której następuje zwrot wyrażenia), oszczędza 3 znaki. Mógłby to zrobić var a; return obj === a;, ale to jeszcze jedna postać. :-)
RobG
2
voidjest słowem zastrzeżonym, podczas gdy undefinednie jest, tzn. gdy domyślnie undefinedjest równe void 0, możesz przypisać wartość undefinednp undefined = 1234.
Brian M. Hunt
isUndefined(obj): 16 znaków. obj === void 0: 14 znaków. - powiedział mniej więcej.
Stijn de Witt
14

Po prostu wszystko nie jest zdefiniowane w JavaScript, jest niezdefiniowane , nie ma znaczenia, czy jest to właściwość wewnątrz Object / Array, czy tylko zwykła zmienna ...

JavaScript ma, typeofdzięki czemu bardzo łatwo jest wykryć niezdefiniowaną zmienną.

Wystarczy sprawdzić, czy typeof whatever === 'undefined'i zwróci wartość logiczną.

Tak isUndefined()napisano słynną funkcję w AngularJs v.1x:

function isUndefined(value) {return typeof value === 'undefined';} 

Gdy zobaczysz, że funkcja odbiera wartość, jeśli ta wartość jest zdefiniowana, zwróci false, w przeciwnym razie zwróci wartość dla niezdefiniowanych wartości true.

Spójrzmy więc, jakie będą wyniki, gdy przekażemy wartości, w tym właściwości obiektu jak poniżej, oto lista zmiennych, które mamy:

var stackoverflow = {};
stackoverflow.javascipt = 'javascript';
var today;
var self = this;
var num = 8;
var list = [1, 2, 3, 4, 5];
var y = null;

i sprawdzamy je jak poniżej, możesz zobaczyć wyniki przed nimi jako komentarz:

isUndefined(stackoverflow); //false
isUndefined(stackoverflow.javascipt); //false
isUndefined(today); //true
isUndefined(self); //false
isUndefined(num); //false
isUndefined(list); //false
isUndefined(y); //false
isUndefined(stackoverflow.java); //true
isUndefined(stackoverflow.php); //true
isUndefined(stackoverflow && stackoverflow.css); //true

Jak widzisz, możemy sprawdzić wszystko za pomocą czegoś takiego w naszym kodzie, jak wspomniano, możesz po prostu użyć typeofw kodzie, ale jeśli używasz go w kółko, utwórz funkcję podobną do próbki kątowej, którą udostępniam i nadal używam jako zgodnie ze wzorem kodu DRY.

I jeszcze jedno, aby sprawdzić właściwość obiektu w prawdziwej aplikacji, której nie jesteś pewien, czy nawet obiekt istnieje, sprawdź, czy obiekt istnieje wcześniej.

Jeśli zaznaczysz właściwość obiektu, a obiekt nie istnieje, zgłosi błąd i zatrzyma działanie całej aplikacji.

isUndefined(x.css);
VM808:2 Uncaught ReferenceError: x is not defined(…)

Tak proste, że możesz zawinąć w instrukcję if, taką jak poniżej:

if(typeof x !== 'undefined') {
  //do something
}

Co również równe jest Zdefiniowane w Angular 1.x ...

function isDefined(value) {return typeof value !== 'undefined';}

Również inne frameworki javascript, takie jak podkreślenie, mają podobną kontrolę definiującą, ale zalecam użycie, typeofjeśli już nie używasz żadnych frameworków.

Dodałem również tę sekcję z MDN, która zawiera przydatne informacje na temat typeof, undefined i void (0).

Ścisła równość i nieokreślone
Można użyć operatorów niezdefiniowanych i ścisłych równości i nierówności, aby ustalić, czy zmienna ma wartość. W poniższym kodzie zmienna x nie jest zdefiniowana, a instrukcja if ma wartość true.

var x;
if (x === undefined) {
   // these statements execute
}
else {
   // these statements do not execute
}

Uwaga: Należy tutaj zastosować operator ścisłej równości zamiast standardowego operatora równości, ponieważ x == undefined sprawdza również, czy x jest zerowy, podczas gdy ścisła równość nie. wartość null nie jest równoważna niezdefiniowanemu. Zobacz szczegóły operatorów.


Operator
typeof i nieokreślony Alternatywnie można użyć typeof:

var x;
if (typeof x === 'undefined') {
   // these statements execute
}

Jednym z powodów użycia typeof jest to, że nie zgłasza błędu, jeśli zmienna nie została zadeklarowana.

// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
   // these statements execute
}

if (x === undefined) { // throws a ReferenceError

}

Tego rodzaju techniki należy jednak unikać. JavaScript jest językiem o statycznym zasięgu, więc wiedząc, czy zmienna jest zadeklarowana, można ją odczytać, sprawdzając, czy jest zadeklarowana w otaczającym kontekście. Jedynym wyjątkiem jest zakres globalny, ale zasięg globalny jest powiązany z obiektem globalnym, więc sprawdzenie istnienia zmiennej w kontekście globalnym można wykonać, sprawdzając istnienie właściwości obiektu globalnego (używając operatora in, na przykład).


Nieważny operator i nieokreślony

Operator void jest trzecią alternatywą.

var x;
if (x === void 0) {
   // these statements execute
}

// y has not been declared before
if (y === void 0) {
   // throws a ReferenceError (in contrast to `typeof`)
}

więcej> tutaj

Alireza
źródło
13

if (window.x) {} ” jest bezpieczny pod względem błędów

Najprawdopodobniej chcesz if (window.x). Ta kontrola jest bezpieczna, nawet jeśli x nie został zadeklarowany ( var x;) - przeglądarka nie zgłasza błędu.

Przykład: Chcę wiedzieć, czy moja przeglądarka obsługuje History API

if (window.history) {
    history.call_some_function();
}

Jak to działa:

window jest obiektem, który przechowuje wszystkie zmienne globalne jako swoje elementy, a próba uzyskania dostępu do nieistniejącego elementu jest legalna. Jeśli x nie zostało zadeklarowane lub nie zostało ustawione, wówczas window.xzwraca niezdefiniowane . niezdefiniowana prowadzi do fałszu, gdy if () ją ocenia.

DenisS
źródło
Ale co, jeśli uruchomisz w węźle? typeof history != 'undefined'faktycznie działa w obu systemach.
Stijn de Witt
13

Czytając to, jestem zdumiony, że tego nie widziałem. Znalazłem wiele algorytmów, które by do tego pasowały.

Nigdy nie zdefiniowano

Jeśli wartość obiektu nigdy nie została zdefiniowana, uniemożliwi to powrót, truejeśli zostanie zdefiniowana jako nulllub undefined. Jest to pomocne, jeśli chcesz zwrócić wartość true dla wartości ustawionych jakoundefined

if(obj.prop === void 0) console.log("The value has never been defined");

Zdefiniowane jako niezdefiniowane lub nigdy nie zdefiniowane

Jeśli chcesz, aby wynik był taki jak truedla wartości zdefiniowanych wartością undefinedlub nigdy nie został zdefiniowany, możesz po prostu użyć=== undefined

if(obj.prop === undefined) console.log("The value is defined as undefined, or never defined");

Zdefiniowane jako wartość fałszowania, niezdefiniowane, zerowe lub nigdy nie zdefiniowane.

Często ludzie pytają mnie o algorytm, aby dowiedzieć się, czy wartość jest fałszem undefined, lub null. Następujące prace.

if(obj.prop == false || obj.prop === null || obj.prop === undefined) {
    console.log("The value is falsy, null, or undefined");
}
Travis
źródło
4
Myślę, że możesz zastąpić ostatni przykład if (!obj.prop)
słowem
@StijndeWitt można, byłem dość niedoświadczony, gdy to pisałem, a mój angielski wydaje się być równie złe, to jednak nie ma nic błędna odpowiedź
Travis
3
var obj = {foo: undefined}; obj.foo === void 0-> true. Jak to się „nigdy nie definiuje jako undefined”? To jest źle.
Patrick Roberts,
@PatrickRoberts Masz rację. Kiedy napisałem tę odpowiedź w lutym 2015 r. (Przed ES6), pierwsza wskazana przeze mnie opcja rzeczywiście działała, ale obecnie jest nieaktualna.
Travis
12
"propertyName" in obj //-> true | false
sam
źródło
10

Porównaj z void 0, dla zwięzłości.

if (foo !== void 0)

To nie jest tak gadatliwe jak if (typeof foo !== 'undefined')

bevacqua
źródło
3
Ale wyrzuci błąd ReferenceError, jeśli nie foozostanie zgłoszony.
daniel1426
1
@ daniel1426: Więc jeśli w kodzie jest błąd, chcesz go ukryć zamiast go naprawić? Niezbyt dobre podejście, IMO.
Nie służy to do ukrywania błędów. Jest to powszechny sposób wykrywania właściwości środowiska w celu zdefiniowania wypełniaczy. Na przykład: if (typeof Promise === 'undefined') {/ * zdefiniuj Promise * /}
gaperton
10

Rozwiązanie jest nieprawidłowe. W JavaScript

null == undefined

zwróci wartość true, ponieważ oba są „rzutowane” na wartość logiczną i są fałszywe. Prawidłowym sposobem byłoby sprawdzenie

if (something === undefined)

który jest operatorem tożsamości ...

Ricky
źródło
3
Żeby było jasne, ===to równość typu + (pierwotna równość | tożsamość obiektu), gdzie pierwotne obejmują łańcuchy. Myślę, że większość ludzi uważa za 'abab'.slice(0,2) === 'abab'.slice(2)nieintuicyjne, jeśli ktoś uważa się ===za operatora tożsamości.
clacke
1
Źle. To powoduje błąd, jeśli zmienna nie została utworzona. Nie należy głosować. Zamiast tego użyj typeof.
Simon East
10

Możesz uzyskać tablicę ze wszystkimi niezdefiniowanymi ścieżkami, używając następującego kodu.

 function getAllUndefined(object) {

        function convertPath(arr, key) {
            var path = "";
            for (var i = 1; i < arr.length; i++) {

                path += arr[i] + "->";
            }
            path += key;
            return path;
        }


        var stack = [];
        var saveUndefined= [];
        function getUndefiend(obj, key) {

            var t = typeof obj;
            switch (t) {
                case "object":
                    if (t === null) {
                        return false;
                    }
                    break;
                case "string":
                case "number":
                case "boolean":
                case "null":
                    return false;
                default:
                    return true;
            }
            stack.push(key);
            for (k in obj) {
                if (obj.hasOwnProperty(k)) {
                    v = getUndefiend(obj[k], k);
                    if (v) {
                        saveUndefined.push(convertPath(stack, k));
                    }
                }
            }
            stack.pop();

        }

        getUndefiend({
            "": object
        }, "");
        return saveUndefined;
    }

Link do jsFiddle

Anoop
źródło
Chociaż nie wpłynie to na ważność twojego kodu, masz literówkę: getUndefiendpowinno być getUndefined.
icktoofay
8

Oto moja sytuacja:

Korzystam z wyniku wywołania REST. Wynik należy przeanalizować z JSON do obiektu JavaScript.

Jest jeden błąd, którego muszę bronić. Jeśli argumenty wywołania reszty były niepoprawne, o ile użytkownik podał błędne argumenty, wywołanie reszty wraca w zasadzie puste.

Korzystając z tego postu, aby pomóc mi się przed tym bronić, próbowałem tego.

if( typeof restResult.data[0] === "undefined" ) { throw  "Some error"; }

W mojej sytuacji, jeśli restResult.data [0] === "obiekt", to mogę bezpiecznie rozpocząć sprawdzanie reszty elementów. Jeśli nie jest zdefiniowany, wyrzuć błąd jak wyżej.

Mówię tylko, że w mojej sytuacji wszystkie powyższe sugestie nie zadziałały. Nie mówię, że mam rację i wszyscy się mylą. W ogóle nie jestem mistrzem JavaScript, ale mam nadzieję, że to komuś pomoże.

wayneseymour
źródło
Twój typeofstrażnik tak naprawdę nie chroni przed niczym, z czym nie poradziłoby sobie bezpośrednie porównanie. Jeśli restResultjest niezdefiniowany lub niezadeklarowany, nadal będzie rzucał.
W twoim przypadku możesz po prostu sprawdzić, czy tablica jest pusta:if(!restResult.data.length) { throw "Some error"; }
Headbank
8

Istnieje przyjemny i elegancki sposób przypisania zdefiniowanej właściwości do nowej zmiennej, jeśli jest ona zdefiniowana, lub przypisania jej wartości domyślnej jako rezerwowej, jeśli jest niezdefiniowana.

var a = obj.prop || defaultValue;

Jest odpowiedni, jeśli masz funkcję, która otrzymuje dodatkową właściwość config:

var yourFunction = function(config){

   this.config = config || {};
   this.yourConfigValue = config.yourConfigValue || 1;
   console.log(this.yourConfigValue);

}

Teraz wykonywana

yourFunction({yourConfigValue:2});
//=> 2

yourFunction();
//=> 1

yourFunction({otherProperty:5});
//=> 1
Marian Klühspies
źródło
7

Wszystkie odpowiedzi są niekompletne. To jest właściwy sposób, aby wiedzieć, że istnieje właściwość „zdefiniowana jako niezdefiniowana”:

var hasUndefinedProperty = function hasUndefinedProperty(obj, prop){
  return ((prop in obj) && (typeof obj[prop] == 'undefined')) ;
} ;

Przykład:

var a = { b : 1, e : null } ;
a.c = a.d ;

hasUndefinedProperty(a, 'b') ; // false : b is defined as 1
hasUndefinedProperty(a, 'c') ; // true : c is defined as undefined
hasUndefinedProperty(a, 'd') ; // false : d is undefined
hasUndefinedProperty(a, 'e') ; // false : e is defined as null

// And now...
delete a.c ;
hasUndefinedProperty(a, 'c') ; // false : c is undefined

Szkoda, że ​​to była prawidłowa odpowiedź zakopana w złych odpowiedziach> _ <

Dla każdego, kto przejedzie, dam ci niezdefiniowane za darmo !!

var undefined ; undefined ; // undefined
({}).a ;                    // undefined
[].a ;                      // undefined
''.a ;                      // undefined
(function(){}()) ;          // undefined
void(0) ;                   // undefined
eval() ;                    // undefined
1..a ;                      // undefined
/a/.a ;                     // undefined
(true).a ;                  // undefined
Juan Garcia
źródło
7

Przeglądając komentarze, dla tych, którzy chcą sprawdzić oba, jest niezdefiniowana lub jej wartość jest null:

//Just in JavaScript
var s; // Undefined
if (typeof s == "undefined" || s === null){
    alert('either it is undefined or value is null')
}

Jeśli używasz biblioteki jQuery jQuery.isEmptyObject(), wystarczy w obu przypadkach,

var s; // Undefined
jQuery.isEmptyObject(s); // Will return true;

s = null; // Defined as null
jQuery.isEmptyObject(s); // Will return true;

//Usage
if (jQuery.isEmptyObject(s)) {
    alert('Either variable:s is undefined or its value is null');
} else {
     alert('variable:s has value ' + s);
}

s = 'something'; // Defined with some value
jQuery.isEmptyObject(s); // Will return false;
Angelin Nadar
źródło
jQuery zajmie się także wszelkimi problemami ze zgodnością różnych przeglądarek z różnymi interfejsami API JavaScript.
Henry Heleine,
7

Jeśli używasz Angulara:

angular.isUndefined(obj)
angular.isUndefined(obj.prop)

Underscore.js:

_.isUndefined(obj) 
_.isUndefined(obj.prop) 
Vitalii Fedorenko
źródło
2
Jak dodać 1do zmiennej x? Czy potrzebuję podkreślenia lub jQuery? (niesamowite, że ludzie będą używać bibliotek do nawet najbardziej podstawowych operacji, takich jak typeofczek)
Stijn de Witt
6

Używam if (this.variable)do testowania, czy to jest zdefiniowane. Proste if (variable), zalecane powyżej , zawodzi dla mnie. Okazuje się, że działa tylko wtedy, gdy zmienna jest polem jakiegoś obiektu, obj.someFieldaby sprawdzić, czy jest zdefiniowana w słowniku. Ale możemy użyć thislub windowjako obiektu słownika, ponieważ jakakolwiek zmienna jest polem w bieżącym oknie, tak jak ja to rozumiem. Dlatego tutaj jest test

if (this.abc) alert("defined"); else alert("undefined");

abc = "abc";
if (this.abc) alert("defined"); else alert("undefined");

Najpierw wykrywa, że ​​zmienna abcjest niezdefiniowana i jest definiowana po inicjalizacji.

Val
źródło
5

Podaję tutaj trzy sposoby dla tych, którzy oczekują dziwnych odpowiedzi:

function isUndefined1(val) {
    try {
        val.a;
    } catch (e) {
        return /undefined/.test(e.message);
    }
    return false;
}
function isUndefined2(val) {
    return !val && val+'' === 'undefined';
}
function isUndefined3(val) {
    const defaultVal={};
    return ((input=defaultVal)=>input===defaultVal)(val);
}
function test(func){
    console.group(`test start :`+func.name);
    console.log(func(undefined));
    console.log(func(null));
    console.log(func(1));
    console.log(func("1"));
    console.log(func(0));
    console.log(func({}));
    console.log(func(function () { }));
    console.groupEnd();
}
test(isUndefined1);
test(isUndefined2);
test(isUndefined3);

isUndefined1:

Spróbuj uzyskać właściwość wartości wejściowej, sprawdź komunikat o błędzie, jeśli istnieje. Jeśli wartość wejściowa jest niezdefiniowana, komunikat o błędzie brzmiałby: Nieprzechwycony typ błędu : Nie można odczytać właściwości „b” niezdefiniowanej

isUndefined2:

Konwertuj wartość wejściową na ciąg znaków, aby porównać "undefined" i upewnij się, że jest to wartość ujemna.

isUndefined3:

W js parametr opcjonalny działa, gdy wartość wejściowa jest dokładnie undefined.

blackmiaool
źródło
4
function isUnset(inp) {
  return (typeof inp === 'undefined')
}

Zwraca false, jeśli zmienna jest ustawiona, a true, jeśli jest niezdefiniowana.

Następnie użyj:

if (isUnset(var)) {
  // initialize variable here
}
Rixius
źródło
5
Nie. Nie rób tego. Wystarczy bardzo prosty test, aby udowodnić, że nie można w sposób znaczący zawinąć typeoftestu w funkcji. Niesamowite, że 4 osoby głosowały za tym. -1.
Stijn de Witt
4

Chciałbym pokazać ci coś, czego używam w celu ochrony undefinedzmiennej:

Object.defineProperty(window, 'undefined', {});

To zabrania nikomu zmiany window.undefinedwartości, a tym samym niszczenia kodu na podstawie tej zmiennej. Jeśli używasz "use strict", wszystko, co próbuje zmienić jego wartość, zakończy się błędem, w przeciwnym razie zostanie po cichu zignorowane.

Seti
źródło
4

możesz także użyć proxy, będzie działać z zagnieżdżonymi wywołaniami, ale będzie wymagał jednego dodatkowego sprawdzenia:

function resolveUnknownProps(obj, resolveKey) {
  const handler = {
    get(target, key) {
      if (
        target[key] !== null &&
        typeof target[key] === 'object'
      ) {
        return resolveUnknownProps(target[key], resolveKey);
      } else if (!target[key]) {
        return resolveUnknownProps({ [resolveKey]: true }, resolveKey);
      }

      return target[key];
    },
  };

  return new Proxy(obj, handler);
}

const user = {}

console.log(resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else); // { isUndefined: true }

więc użyjesz go jak:

const { isUndefined } = resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else;
if (!isUndefined) {
  // do someting
}
Sarkis Arutiunian
źródło
4

Z lodash.js.

var undefined;
function isUndefined(value) {
  return value === undefined;
}

Tworzy zmienną LOCAL o nazwie, undefinedktóra jest inicjowana wartością domyślną - rzeczywistą undefined, a następnie porównywana valueze zmienną undefined.


Aktualizacja 9.09.2019

Odkryłem, że lodash zaktualizował jego wdrożenie. Zobacz mój problem i kod .

Aby być kuloodpornym, po prostu użyj:

function isUndefined(value) {
  return value === void 0;
}
lzl124631x
źródło