Detectando uma propriedade de objeto indefinida

2841

Qual é a melhor maneira de verificar se uma propriedade de objeto em JavaScript é undefined?

Matt Sheppard
fonte

Respostas:

2681

A maneira usual de verificar se o valor de uma propriedade é o valor especial undefinedé:

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

Para verificar se um objeto realmente não tem essa propriedade e, portanto, retornará undefinedpor padrão quando você tentar acessá-lo:

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

Para verificar se o valor associado a um identificador é o valor especial undefined, ou se esse identificador não foi declarado. Nota: este método é a única maneira de se referir a um identificador não declarado (nota: diferente de ter um valor de undefined) sem um erro precoce:

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

Nas versões do JavaScript anteriores ao ECMAScript 5, a propriedade denominada "undefined" no objeto global era gravável e, portanto, uma verificação simples foo === undefinedpode se comportar inesperadamente se ela tiver sido redefinida acidentalmente. No JavaScript moderno, a propriedade é somente leitura.

No entanto, no JavaScript moderno, "undefined" não é uma palavra-chave e, portanto, variáveis ​​dentro de funções podem ser nomeadas "undefined" e sombrear a propriedade global.

Se você estiver preocupado com esse caso improvável (edge), poderá usar o operador void para obter o undefinedpróprio valor especial :

if(myVariable === void 0) {
  alert("myVariable is the special value `undefined`");
}
Ry-
fonte
9
se algo for nulo, ele será definido (como nulo), mas você poderá conjugar as verificações demais. O detalhe irritante do código acima é que você não pode definir uma função para verificá-la, bem, você pode definir a função ... mas tente usá-la.
N / a n / a rah
5
@ neu-rah, por que você não pode escrever uma função? por que algo assim não funcionaria? Parece funcionar para mim. Existe um caso que eu não estou considerando? jsfiddle.net/djH9N/6
Zack
7
@Zack Seus testes para isNullorUndefined não consideraram o caso em que você chama isNullOrUndefined (f) ef não foi declarado (ou seja, onde não há declaração "var f").
Pnkfelix
109
Blah, milhares de votos agora. Esta é a pior maneira possível de fazê-lo. Espero que os transeuntes vejam esse comentário e decidam verificar ... ah ... outras respostas.
Ry-
17
Você pode apenas usar obj !== undefinedagora. undefinedcostumava ser mutável, como undefined = 1234o que causaria resultados interessantes. Mas depois do Ecmascript 5, ele não pode mais ser gravado, para que possamos usar a versão mais simples. codereadability.com/how-to-check-for-undefined-in-javascript
de Bruno Buccolo
899

Acredito que haja várias respostas incorretas para esse tópico. Ao contrário do que se pensa, "indefinido" não é uma palavra-chave em JavaScript e pode de fato ter um valor atribuído a ela.

Código correto

A maneira mais robusta de executar este teste é:

if (typeof myVar === "undefined")

Isso sempre retornará o resultado correto e até lida com a situação em que myVarnão é declarado.

Código degenerado. NÃO USE.

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

Além disso, myVar === undefinedhaverá um erro na situação em que myVar não for declarado.

MarkPflug
fonte
133
+1 por observar que myVar === indefinido gerará um erro se o myVar não for declarado #
Enrique
73
Acho a primeira justificativa dada aqui para não usar === undefineddesconcertante. Sim, você pode atribuir a undefined, mas não há motivo legítimo para fazê-lo, e é previsível que isso possa danificar seu código. Em C você pode #define true false, e em Python você pode atribuir a Truee False, mas as pessoas não sentem a necessidade de projetar seu código nessas línguas, de tal forma a proteger contra a possibilidade de eles próprios deliberadamente sabotando seu próprio ambiente em outras partes do código . Por que a possibilidade de atribuir undefinedaté vale a pena considerar aqui?
Mark Amery
19
além dos comentários de Marks, não entendi: "myVar === indefinido gerará um erro na situação em que myVar não for declarado". - por que isso é ruim? Por que não gostaria de ter um erro se estiver referenciando variáveis ​​não declaradas?
eis
5
Lembre-se também de que você sempre pode void 0obter o valor que undefinedaponta para. Então você pode fazer if (myVar === void 0). o 0não é especial, você pode literalmente colocar qualquer expressão lá.
Claudiu
28
Nos navegadores modernos (FF4 +, IE9 +, Chrome desconhecido), não é mais possível modificar undefined. MDN: undefined
user247702
228

Apesar de ser veementemente recomendado por muitas outras respostas aqui, typeof é uma má escolha . Ele nunca deve ser usado para verificar se as variáveis ​​têm o valor undefined, porque atua como uma verificação combinada do valor undefinede da existência de uma variável. Na grande maioria dos casos, você sabe quando existe uma variável e typeofapenas apresentará o potencial para uma falha silenciosa se você digitar um erro de digitação no nome da variável ou na string literal '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!
}

Portanto, a menos que você esteja realizando a detecção de recursos², onde há incerteza quanto ao escopo de um determinado nome (como verificar typeof module !== 'undefined'uma etapa no código específico de um ambiente CommonJS), typeofé uma escolha prejudicial quando usada em uma variável, e a opção correta é para comparar o valor diretamente:

var foo = …;

if (foo === undefined) {
    
}

Alguns equívocos comuns sobre isso incluem:

  • que a leitura de uma variável "não inicializada" ( var foo) ou de um parâmetro ( function bar(foo) { … }chamado como bar()) falhará. Isso simplesmente não é verdade - variáveis ​​sem inicialização explícita e parâmetros que não receberam valores sempre se tornam undefinede estão sempre no escopo.

  • que undefinedpode ser substituído. Há muito mais nisso. undefinednão é uma palavra-chave em JavaScript. Em vez disso, é uma propriedade no objeto global com o valor Indefinido. No entanto, desde ES5, essa propriedade é somente leitura e não configurável . Nenhum navegador moderno permitirá que a undefinedpropriedade seja alterada e, a partir de 2017, esse é o caso há muito tempo. A falta de modo estrito também não afeta undefinedo comportamento - apenas faz declarações como undefined = 5não fazer nada em vez de jogar. Como não é uma palavra-chave, você pode declarar variáveis ​​com o nome undefined, e essas variáveis ​​podem ser alteradas, criando esse padrão outrora comum:

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

    mais perigoso do que usar o global undefined. Se você precisar ser compatível com ES3, substitua undefinedpor void 0- não use typeof. ( voidsempre foi um operador unário que avalia o valor Indefinido para qualquer operando.)

Com como as variáveis ​​funcionam fora do caminho, é hora de abordar a questão real: propriedades do objeto. Não há motivo para nunca usar typeofpara propriedades de objetos. A exceção anterior referente à detecção de recursos não se aplica aqui - typeofpossui apenas comportamento especial em variáveis ​​e expressões que referenciam propriedades de objetos não são variáveis.

Este:

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

é sempre exatamente equivalente a este³:

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

e levando em consideração o conselho acima, para evitar confundir os leitores sobre o motivo pelo qual você está usando typeof, porque faz mais sentido usar ===para verificar a igualdade, porque pode ser refatorado para verificar o valor de uma variável mais tarde e simplesmente parece melhor, você sempre deve usar === undefined³ aqui também .

Outra coisa a considerar quando se trata de propriedades do objeto é se você realmente deseja verificar undefined. Um determinado nome de propriedade pode estar ausente em um objeto (produzindo o valor undefinedquando lido), presente no próprio objeto com o valor undefined, presente no protótipo do objeto com o valor undefinedou presente em qualquer um que não tenha undefinedvalor. 'key' in objinformará se uma chave está em algum lugar da cadeia de protótipos de um objeto e Object.prototype.hasOwnProperty.call(obj, 'key')informará se está diretamente no objeto. Porém, não vou entrar em detalhes nesta resposta sobre protótipos e no uso de objetos como mapas com chave de cadeia, porque o objetivo principal é combater todos os maus conselhos em outras respostas, independentemente das possíveis interpretações da pergunta original. Leia sobreprotótipos de objetos no MDN para mais!

¹ escolha incomum do exemplo do nome da variável? esse é um código morto real da extensão NoScript para Firefox.
² não assuma que não saber o que está no escopo é bom, em geral. vulnerabilidade de bônus causada por abuso de escopo dinâmico: Projeto Zero 1225
³ mais uma vez assumindo um ambiente ES5 + e que undefinedse refere à undefinedpropriedade do objeto global. substituir de void 0outra forma.

Ry-
fonte
@BenjaminGruenbaum Verdadeiro, mas completamente enganador. Qualquer contexto não padrão pode definir seu próprio undefined, ocultando o contexto padrão. Que, para fins mais práticos, tem o mesmo efeito que sobrescrevê-lo.
blgt
23
@blgt Isso é paranóico e irrelevante para qualquer coisa prática. Todo contexto pode substituir o console.log, redefinir os métodos de protótipo de matriz e até substituir o engate de Function.prototype.call` e alterar toda vez que você chama uma função em JavaScript. Proteger contra isso é muito paranóico e bastante tolo. Como eu (e a minitech) disse, você pode void 0comparar com o indefinido, mas novamente - isso é bobagem e exagero.
Benjamin Gruenbaum
19
Eu gostaria de ter mais de um voto positivo para dar. Esta é a resposta mais correta. Eu realmente quero parar de ver typeof something === "undefined") no código.
Simon Baumgardt-Wellander
@BenjaminGruenbaum Para programadores preguiçosos, void 0é (pela primeira vez) mais curto e mais seguro! Isso é uma vitória no meu livro.
Wizzwizz4
4
Esta realmente deve ser a resposta aceita. É o mais completo e atualizado.
Patrick Michaelsen
161

No JavaScript, há nulo e indefinido . Eles têm significados diferentes.

  • indefinido significa que o valor da variável não foi definido; não se sabe qual é o valor.
  • nulo significa que o valor da variável está definido e definido como nulo (não possui valor).

Marijn Haverbeke declara, em seu livro on-line gratuito " JavaScript eloquente " (grifo meu):

Também existe um valor semelhante, null, cujo significado é 'esse valor é definido, mas não possui um valor'. A diferença de significado entre indefinido e nulo é principalmente acadêmica e geralmente não é muito interessante. Nos programas práticos, muitas vezes é necessário verificar se algo 'tem um valor'. Nesses casos, a expressão algo == indefinido pode ser usada, porque, embora não sejam exatamente o mesmo valor, nulo == indefinido produzirá verdadeiro.

Então, acho que a melhor maneira de verificar se algo estava indefinido seria:

if (something == undefined)

Espero que isto ajude!

Editar: em resposta à sua edição, as propriedades do objeto devem funcionar da mesma maneira.

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

alert(person.name); // "John"
alert(person.fakeVariable); // undefined
Pandincus
fonte
42
if (algo == indefinido) é melhor escrito como se (algo === indefinido)
Sebastian Rittau
59
Vale ressaltar que isso não é totalmente seguro. undefinedé apenas uma variável que pode ser reatribuída pelo usuário: a gravação undefined = 'a';fará com que seu código não faça mais o que você pensa. Usar typeofé melhor e também funciona para variáveis ​​(não apenas propriedades) que não foram declaradas.
precisa saber é o seguinte
7
se algo é uma variável global indefinida, (algo == indefinido) gera um erro de javascript.
Morgan Cheng
8
O problema disso é que, se var a = null, um == undefined é avaliado como true, mesmo que a esteja certamente definido.
18711 Andrew
6
Essa interpretação do comentário "Eloquent Javascript" é reversa . Se você realmente deseja apenas verificar indefinidos, o código sugerido não funcionará (ele também detectará a condição definida, mas nenhum valor foi atribuído ainda [ienull]). Um valor nulo. O código sugerido "if (algo == indefinido) ..." verifica tanto indefinido quanto nulo (sem valor definido), ou seja, é interpretado como "se ((algo não definido) OU (algo é nulo)) ..." o que o autor está dizendo é que muitas vezes o que você realmente quer é para verificar se há tanto indefinido e nulo.
Chuck Kollars
125

O que isso significa: "propriedade de objeto indefinida" ?

Na verdade, pode significar duas coisas bem diferentes! Primeiro, pode significar a propriedade que nunca foi definida no objeto e, segundo, pode significar a propriedade que possui um valor indefinido . Vamos olhar para este código:

var o = { a: undefined }

Está o.aindefinido? Sim! Seu valor é indefinido. Está o.bindefinido? Certo! Não existe nenhuma propriedade 'b'! OK, veja agora como diferentes abordagens se comportam nas duas situações:

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

Podemos ver claramente isso typeof obj.prop == 'undefined'e obj.prop === undefinedsão equivalentes, e eles não distinguem essas diferentes situações. E 'prop' in objpode detectar a situação quando uma propriedade ainda não foi definida e não presta atenção ao valor da propriedade que pode ser indefinido.

Então o que fazer?

1) Você deseja saber se uma propriedade é indefinida pelo primeiro ou pelo segundo significado (a situação mais típica).

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

2) Você quer apenas saber se o objeto tem alguma propriedade e não se importa com o seu valor.

'prop' in obj

Notas:

  • Você não pode verificar um objeto e sua propriedade ao mesmo tempo. Por exemplo, isso x.a === undefinedou isso typeof x.a == 'undefined'aumenta ReferenceError: x is not definedse x não estiver definido.
  • Variável undefinedé uma variável global (na verdade, ela está window.undefinednos navegadores). É suportado desde o ECMAScript 1st Edition e, desde o ECMAScript 5, é somente leitura . Portanto, em navegadores modernos, não pode ser redefinido para verdadeiro, como muitos autores adoram nos assustar, mas isso ainda é válido para navegadores mais antigos.

Luta final: obj.prop === undefinedvstypeof obj.prop == 'undefined'

Vantagens de obj.prop === undefined:

  • É um pouco mais curto e parece um pouco mais bonito
  • O mecanismo JavaScript apresentará um erro se você tiver escrito incorretamente undefined

Desvantagens de obj.prop === undefined:

  • undefined pode ser substituído em navegadores antigos

Vantagens de typeof obj.prop == 'undefined':

  • É realmente universal! Funciona em navegadores novos e antigos.

Desvantagens de typeof obj.prop == 'undefined':

  • 'undefned'( erro de ortografia ) aqui é apenas uma constante de cadeia de caracteres, portanto, o mecanismo JavaScript não pode ajudá-lo se você o tiver digitado incorretamente, como eu acabei de fazer.

Atualização (para JavaScript do servidor):

O Node.js suporta a variável global undefinedcomo global.undefined(também pode ser usada sem o prefixo 'global'). Não conheço outras implementações de JavaScript do lado do servidor.

Konstantin Smolyanin
fonte
@ Bergi obrigado pelo seu comentário. Eu corrigi minha resposta. Em minha defesa, posso dizer que atualmente (a partir da versão 1.0.10.18) a documentação oficial do Node.js. não diz nada sobre undefinedcomo membro global. Também nem console.log(global);nem for (var key in global) { ... }não aparece indefinido como membro do global . Mas teste como 'undefined' in globalmostre o oposto.
Konstantin Smolyanin
4
Ele não precisava de documentação adicional, uma vez que é na EcmaScript especificação , que também diz que [[Enumerable]]é falsa :-)
Bergi
5
Em relação a Minuses of typeof obj.prop == 'undefined'isso, isso pode ser evitado escrevendo como typeof obj.prop == typeof undefined. Isso também fornece uma simetria muito agradável.
hlovdal
3
@hlovdal: Isso é totalmente inútil vs. obj.prop === undefined.
Ry-
1
Quando somos fiéis ao título da pergunta Detectando uma propriedade indefinida“ , não fiel à pergunta (diferente e muito mais fácil) na primeira frase (“verifique se indefinido ...”), você responde if ('foo' in o)… sua resposta é realmente a primeira resposta correta aqui. Quase todo mundo apenas responde essa frase.
precisa
70

O problema se resume a três casos:

  1. O objeto tem a propriedade e seu valor não undefined.
  2. O objeto tem a propriedade e seu valor é undefined.
  3. O objeto não possui a propriedade

Isso nos diz algo que considero importante:

Há uma diferença entre um membro indefinido e um membro definido com um valor indefinido.

Mas infelizmente typeof obj.foonão nos diz qual dos três casos que temos. No entanto, podemos combinar isso com "foo" in objpara distinguir os casos.

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

Vale ressaltar que esses testes também são iguais para as nullentradas

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

Eu diria que, em alguns casos, faz mais sentido (e é mais claro) verificar se a propriedade existe, do que verificar se está indefinida, e o único caso em que essa verificação será diferente é o caso 2, o raro caso de uma entrada real no objeto com um valor indefinido.

Por exemplo: Acabei de refatorar um monte de código que tinha um monte de verificações se um objeto tinha uma determinada propriedade.

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

O que ficou mais claro quando escrito sem um cheque por indefinido.

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

Mas, como já foi mencionado, estes não são exatamente os mesmos (mas são mais do que suficientes para minhas necessidades).

Michael Anderson
fonte
10
Olá Michael. Ótima sugestão, e acho que isso torna as coisas mais limpas. Uma pegadinha que eu encontrei, no entanto, é ao usar o! operador com "in". Você tem que dizer if (!("x" in blob)) {}entre parênteses, porque o! O operador tem precedência sobre 'in'. Espero que ajude alguém.
Simon Médio
Desculpe Michael, mas isso está incorreto, ou pelo menos enganoso, à luz da pergunta original. 'in' não é uma maneira suficiente de testar se uma propriedade de objeto tem o tipo de indefinido. Para prova, veja este violino: jsfiddle.net/CsLKJ/4
tex
2
Essas duas partes do código fazem uma coisa diferente! Considere e objeto dado por a = {b: undefined}; então typeof a.b === typeof a.c === 'undefined'mas 'b' in ae !('c' in a).
mgol 27/09/12
3
+1. O OP não deixa claro se a propriedade existe e tem o valor indefinido ou se a propriedade em si é indefinida (ou seja, não existe).
RobG
Eu sugeriria alterar o ponto (2.) em sua primeira tabela { x : undefined }ou, pelo menos, adicioná-lo como outra alternativa a (2.) na tabela - tive que pensar por um momento para perceber que o ponto (2.) avalia undefined(embora você mencionou isso mais tarde).
Mucaho 14/05
46
if ( typeof( something ) == "undefined") 

Isso funcionou para mim, enquanto os outros não.

Kevin
fonte
47
parens são desnecessárias desde typeof é um operador
aehlke
12
Mas eles esclarecem o que está sendo verificado. Caso contrário, pode ser lido como typeof (something == "undefined").
Abhi Beckert
Se você precisa dos parênteses, então você deve aprender a precedência de operador em JS: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
Ian
11
Os parênteses são úteis precisamente porque você NÃO precisa aprender a precedência do operador em JS, nem precisa especular se futuros programadores de manutenção precisarão aprender a precedência do operador em JS.
DaveWalley
27
Parênteses são úteis para esclarecer as coisas. Mas, neste caso, eles apenas fazem o operador parecer uma função. Sem dúvida, isso esclarece a intenção do programador. Mas se você não tiver certeza sobre a precedência do operador, deve escrever como (typeof something) === "undefined".
Robert
42

Não tenho certeza de onde a origem de usar ===com typeofveio, e como uma convenção que eu vê-lo usado em muitas bibliotecas, mas o operador typeof retorna um literal de cadeia, e sabemos que frente-se, então por que você também quiser tipo verificá-lo também?

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
fonte
Ótimo ponto Eric. Existe um impacto no desempenho ao verificar o tipo também?
Simon East
5
@ Simon: muito pelo contrário - pode-se esperar um leve impacto no desempenho ao evitar a coerção no caso '==='. Teste rápido e sujo mostrou que '===' é 5% mais rápido que '==' sob FF5.0.1
Antony Hatchkins
5
Testes mais detalhados mostraram que no FF, IE e Chrome '==' é mais ou menos mais rápido que '===' (5-10%) e o Opera não faz nenhuma diferença: jsperf.com/triple- equals-vs-
two
3
O uso ==ainda requer pelo menos uma verificação de tipo - o intérprete não pode comparar os dois operandos sem conhecer seu tipo primeiro.
Alnitak
7
==é menos um personagem que ===:)
svidgen
25

Como cruzar minha resposta de uma pergunta relacionada Como verificar se há "indefinido" em JavaScript?

Específico para esta pergunta, consulte casos de teste com someObject.<whatever>.


Alguns cenários ilustrando os resultados das várias respostas: http://jsfiddle.net/drzaus/UVjM4/

(Observe que o uso de varpara intestes faz diferença quando em um invólucro com escopo definido)

Código de referência:

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

E resultados:

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
fonte
21

Se você fizer

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

falhará quando a variável myvarnão existir, porque myvar não está definido; portanto, o script está quebrado e o teste não tem efeito.

Como o objeto da janela possui um escopo global (objeto padrão) fora de uma função, uma declaração será 'anexada' ao objeto da janela.

Por exemplo:

var myvar = 'test';

A variável global myvar é igual a window.myvar ou window ['myvar']

Para evitar erros ao testar quando existe uma variável global, é melhor usar:

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

A pergunta se uma variável realmente existe não importa, seu valor está incorreto. Caso contrário, é bobagem inicializar variáveis ​​com indefinidas e é melhor usar o valor false para inicializar. Quando você souber que todas as variáveis ​​declaradas foram inicializadas com false, basta verificar seu tipo ou confiar !window.myvarpara verificar se ele possui um valor apropriado / válido. Portanto, mesmo quando a variável não está definida, !window.myvaré a mesma para myvar = undefinedor myvar = falseou myvar = 0.

Quando você espera um tipo específico, teste o tipo da variável. Para acelerar o teste de uma condição, é melhor:

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

Quando a primeira e simples condição for verdadeira, o intérprete pula os próximos testes.

É sempre melhor usar a instância / objeto da variável para verificar se ela obteve um valor válido. É mais estável e é uma maneira melhor de programação.

y)

Codebeat
fonte
19

Não vi (espero não ter perdido) ninguém verificando o objeto antes da propriedade. Portanto, este é o mais curto e mais eficaz (embora não necessariamente o mais claro):

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

Se o obj ou obj.prop for indefinido, nulo ou "falso", a instrução if não executará o bloco de código. Geralmente, esse é o comportamento desejado na maioria das instruções de bloco de código (em JavaScript).

Joe Johnson
fonte
2
Se você quer saber por que isso funciona: javascript: Operadores lógicos e truthy / Falsas
MB21
se você deseja atribuir a propriedade a uma variável, se ela estiver definida, não nula e não falsey, caso contrário, use algum valor padrão, você pode usar: var x = obj && obj.prop || 'default';
Stijn de Witt
Acredito que a pergunta é para verificar explicitamente o indefinido. Sua condição verifica todos os valores falsos de JS.
NikoKyriakid
15

No artigo Explorando o abismo de nulo e indefinido em JavaScript , li que estruturas como Underscore.js usam esta função:

function isUndefined(obj){
    return obj === void 0;
}
Marthijn
fonte
3
void 0é apenas uma maneira curta de escrever undefined(já que é o que o nulo seguido por qualquer expressão retorna), ele salva 3 caracteres. Também poderia funcionar var a; return obj === a;, mas esse é mais um personagem. :-)
RobG 01/04
2
voidé uma palavra reservada, enquanto que undefinednão é ie, enquanto undefinedé igual void 0por padrão, você pode atribuir um valor a undefinedeg undefined = 1234.
Brian M. caça
isUndefined(obj): 16 caracteres. obj === void 0: 14 caracteres. disse quase.
Stijn de Witt
14

Simplesmente qualquer coisa não está definida em JavaScript, é indefinida , não importa se é uma propriedade dentro de um Object / Array ou apenas como uma variável simples ...

O JavaScript typeoffacilita a detecção de uma variável indefinida.

Basta verificar se typeof whatever === 'undefined'e ele retornará um booleano.

É assim que a famosa função isUndefined()no AngularJs v.1x é escrita:

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

Portanto, como você vê a função receber um valor, se esse valor for definido, ele retornará false, caso contrário, para valores indefinidos, retornará true.

Então, vamos dar uma olhada nos resultados quando passarmos valores, incluindo propriedades de objetos, como abaixo, esta é a lista de variáveis ​​que temos:

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

e verificamos como abaixo, você pode ver os resultados na frente deles como um comentário:

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

Como você vê, podemos verificar qualquer coisa usando algo parecido com isto em nosso código, como mencionado, você pode simplesmente usar typeofem seu código, mas se você o estiver usando repetidamente, crie uma função como a amostra angular que eu compartilho e continuo reutilizando como seguindo o padrão de código DRY.

Além disso, mais uma coisa: para verificar a propriedade de um objeto em um aplicativo real que você não tem certeza, mesmo que o objeto exista ou não, verifique se o objeto existe primeiro.

Se você marcar uma propriedade em um objeto e o objeto não existir, lançará um erro e interromperá a execução de todo o aplicativo.

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

Tão simples que você pode envolver dentro de uma declaração if como abaixo:

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

Qual também igual a isDefined no Angular 1.x ...

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

Outras estruturas javascript, como o sublinhado, também possuem verificação de definição semelhante, mas eu recomendo que você use typeofse você já não estiver usando nenhuma estrutura.

Também adiciono esta seção do MDN, que possui informações úteis sobre typeof, undefined e void (0).

Igualdade estrita e indefinida
É possível usar operadores de igualdade e desigualdade indefinidos e estritos para determinar se uma variável tem um valor. No código a seguir, a variável x não está definida e a instrução if é avaliada como verdadeira.

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

Nota: O operador de igualdade estrita, em vez do operador de igualdade padrão, deve ser usado aqui, porque x == undefined também verifica se x é nulo, enquanto a igualdade estrita não. null não é equivalente a indefinido. Consulte operadores de comparação para obter detalhes.


Operador Typeof e indefinido
Como alternativa, typeof pode ser usado:

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

Um motivo para usar typeof é que ele não gera um erro se a variável não tiver sido declarada.

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

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

}

No entanto, esse tipo de técnica deve ser evitado. JavaScript é uma linguagem com escopo estaticamente, portanto, saber se uma variável é declarada pode ser lido, verificando se ela é declarada em um contexto fechado. A única exceção é o escopo global, mas o escopo global está vinculado ao objeto global, portanto, a verificação da existência de uma variável no contexto global pode ser feita verificando a existência de uma propriedade no objeto global (usando o operador in, por exemplo).


Operador nulo e indefinido

O operador nulo é uma terceira alternativa.

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`)
}

mais> aqui

Alireza
fonte
13

' if (window.x) {} ' é seguro contra erros

Provavelmente você quer if (window.x). Essa verificação é segura mesmo que x não tenha sido declarado ( var x;) - o navegador não gera um erro.

Exemplo: quero saber se meu navegador suporta a API do histórico

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

Como isso funciona:

window é um objeto que mantém todas as variáveis ​​globais como seus membros e é legal tentar acessar um membro não existente. Se x não foi declarado ou não foi definido, window.xretornará indefinido . undefined leva a false quando if () avalia.

DenisS
fonte
Mas e se você executar no Node? typeof history != 'undefined'realmente funciona nos dois sistemas.
Stijn de Witt
13

Ao ler isso, estou surpreso por não ter visto isso. Eu encontrei vários algoritmos que funcionariam para isso.

Nunca definido

Se o valor de um objeto nunca foi definido, isso impedirá o retorno truese for definido como nullou undefined. Isso é útil se você deseja que true seja retornado para valores definidos comoundefined

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

Definido como indefinido ou nunca definido

Se você deseja que resulte como truepara valores definidos com o valor de undefined, ou nunca definidos, você pode simplesmente usar=== undefined

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

Definido como um valor falso, indefinido, nulo ou nunca definido.

Geralmente, as pessoas me pedem um algoritmo para descobrir se um valor é falso undefined, ou null. Os seguintes trabalhos.

if(obj.prop == false || obj.prop === null || obj.prop === undefined) {
    console.log("The value is falsy, null, or undefined");
}
Travis
fonte
4
Eu acho que você pode substituir o último exemplo porif (!obj.prop)
Stijn de Witt
@StijndeWitt, você pode, eu estava muito inexperiente quando eu escrevi isto, e meu Inglês parece ter sido igualmente ruim, no entanto, não há nada de errado na resposta
Travis
3
var obj = {foo: undefined}; obj.foo === void 0-> true. Como isso é "nunca definido como undefined"? Isto está errado.
Patrick Roberts
@PatrickRoberts Você está certo. Quando escrevi esta resposta em fevereiro de 2015 (antes do ES6), a primeira opção que descrevi realmente funcionou, mas agora está desatualizada.
Travis
12
"propertyName" in obj //-> true | false
sam
fonte
10

Compare com void 0, por concisão.

if (foo !== void 0)

Não é tão detalhado quanto if (typeof foo !== 'undefined')

bevacqua
fonte
3
Mas lançará um ReferenceError se foonão for declarado.
Daniel1426 7/03/2014
1
@ daniel1426: Então, se houver um erro no seu código, você deseja ocultá-lo em vez de corrigi-lo? Não é uma ótima abordagem, IMO.
Isso não é usado para ocultar erros. É a maneira comum de detectar as propriedades do ambiente para definir polyfills. Por exemplo: if (typeof Promise === 'undefined') {/ * define Promise * /}
gaperton
10

A solução está incorreta. Em JavaScript,

null == undefined

retornará true, porque ambos são "convertidos" para um booleano e são falsos. A maneira correta seria verificar

if (something === undefined)

que é o operador de identidade ...

Ricky
fonte
3
Para ser claro, ===digite tipo igualdade + (igualdade primitiva | identidade do objeto), em que os primitivos incluem cadeias. Acho que a maioria das pessoas considera 'abab'.slice(0,2) === 'abab'.slice(2)não intuitivo se considerarmos ===o operador de identidade.
Clacke
1
Errado. Isso gera um erro se a variável não tiver sido criada. Não deve ser votado. Use typeof em vez disso.
Simon Médio
10

Você pode obter uma matriz toda indefinida com o caminho usando o código a seguir.

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

jsFiddle link

Anoop
fonte
Embora isso não afete a validade do seu código, você tem um erro de digitação: getUndefienddeveria getUndefined.
icktoofay
8

Aqui está a minha situação:

Estou usando o resultado de uma chamada REST. O resultado deve ser analisado do JSON para um objeto JavaScript.

Há um erro que preciso defender. Se os argumentos à chamada restante estavam incorretos, na medida em que o usuário especificou os argumentos incorretos, a chamada restante volta basicamente vazia.

Ao usar este post para me ajudar a me defender, tentei isso.

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

Para minha situação, se restResult.data [0] === "objeto", então posso começar a inspecionar com segurança o restante dos membros. Se indefinido, jogue o erro como acima.

O que estou dizendo é que, para minha situação, todas as sugestões acima neste post não funcionaram. Não estou dizendo que estou certo e todo mundo está errado. Eu não sou um mestre de JavaScript, mas espero que isso ajude alguém.

wayneseymour
fonte
Seu typeofguarda não se protege contra nada que uma comparação direta não possa suportar. Se restResultfor indefinido ou não declarado, ainda será lançado.
No seu caso, você poderia simplesmente verificar se a matriz está vazia:if(!restResult.data.length) { throw "Some error"; }
Headbank 28/02/19
8

Existe uma maneira agradável e elegante de atribuir uma propriedade definida a uma nova variável, se ela estiver definida, ou atribuir um valor padrão a ela como substituto, se não for definido.

var a = obj.prop || defaultValue;

É adequado se você tiver uma função que receba uma propriedade de configuração adicional:

var yourFunction = function(config){

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

}

Agora executando

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

yourFunction();
//=> 1

yourFunction({otherProperty:5});
//=> 1
Marian Klühspies
fonte
7

Todas as respostas estão incompletas. Esta é a maneira correta de saber que existe uma propriedade 'definida como indefinida':

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

Exemplo:

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

Pena que esta foi a resposta certa, está enterrada em respostas erradas> _ <

Então, para quem passa, eu te darei indefinidos de graça !!

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
fonte
7

Analisando os comentários, para quem deseja verificar os dois é indefinido ou seu valor é nulo:

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

Se você estiver usando a biblioteca jQuery, jQuery.isEmptyObject()será suficiente para ambos os casos,

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
fonte
O jQuery também cuidará de quaisquer problemas de compatibilidade entre navegadores com as diferentes APIs JavaScript.
Henry Heleine
7

Se você estiver usando Angular:

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

Underscore.js:

_.isUndefined(obj) 
_.isUndefined(obj.prop) 
Vitalii Fedorenko
fonte
2
Como adiciono 1à variável x? Preciso de sublinhado ou jQuery? (incrível que as pessoas vão usar bibliotecas mesmo para os mais operações elementares, como um typeofcheque)
Stijn de Witt
6

Eu uso if (this.variable)para testar se está definido. Simples if (variable), recomendado acima , falha para mim. Acontece que ele funciona apenas quando variável é um campo de algum objeto, obj.someFieldpara verificar se está definido no dicionário. Mas podemos usar thisou windowcomo objeto de dicionário, já que qualquer variável é um campo na janela atual, pelo que entendi. Portanto, aqui está um teste

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

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

Ele primeiro detecta que a variável não abcestá definida e é definida após a inicialização.

Val
fonte
5

Eu forneço três maneiras aqui para aqueles que esperam respostas estranhas:

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:

Tente obter uma propriedade do valor de entrada, verifique a mensagem de erro, se existir. Se o valor de entrada for indefinido, a mensagem de erro será Uncaught TypeError: Não é possível ler a propriedade 'b' de undefined

isUndefined2:

Converta o valor de entrada em string para comparar "undefined"e garantir que seja um valor negativo.

isUndefined3:

Em js, o parâmetro opcional funciona quando o valor de entrada é exatamente undefined.

blackmiaool
fonte
5

O ES2019 introduziu um novo recurso - encadeamento opcional que você pode usar para usar uma propriedade de um objeto apenas quando um objeto é definido assim:

const userPhone = user?.contactDetails?.phone;

Ele fará referência à propriedade phone somente quando user e contactDetails estiverem definidos.

Ref. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

Przemek Struciński
fonte
Eu costumava usar muito a função do lodash, muito conveniente para acessar esse tipo de objetos, mas o novo encadeamento opcional cobre a maioria dos usos de _.get
Al Hill
4
function isUnset(inp) {
  return (typeof inp === 'undefined')
}

Retorna false se a variável estiver definida e true se não for definido.

Então use:

if (isUnset(var)) {
  // initialize variable here
}
Rixius
fonte
5
Não. Não faça isso. É necessário apenas um teste muito simples para provar que você não pode agrupar significativamente um typeofteste em uma função. Incrível que 4 pessoas votaram positivamente nisso. -1.
Stijn de Witt
4

Gostaria de mostrar uma coisa que estou usando para proteger a undefinedvariável:

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

Isso proíbe qualquer pessoa de alterar o window.undefinedvalor, destruindo o código com base nessa variável. Se estiver usando "use strict", qualquer coisa que tente alterar seu valor terminará em erro, caso contrário, seria silenciosamente ignorado.

Seti
fonte
4

você também pode usar o Proxy, ele funcionará com chamadas aninhadas, mas exigirá uma verificação extra:

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 }

então você o usará como:

const { isUndefined } = resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else;
if (!isUndefined) {
  // do someting
}
Sarkis Arutiunian
fonte