Como verificar se há “indefinido” em JavaScript?

Qual é a maneira mais apropriada de testar se uma variável é indefinida em JavaScript? Eu vi várias maneiras possíveis:

if (window.myVariable) 

Ou

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

Ou

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

Se você estiver interessado em descobrir se uma variável foi declarada, independentemente de seu valor, usar o operador in é a maneira mais segura de ir. Considere este exemplo.

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

Mas isso pode não ser o resultado pretendido para alguns casos, uma vez que a variável ou propriedade foi declarada, mas não inicializada. Use o operador in para uma verificação mais robusta.

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

Se você estiver interessado em saber se a variável não foi declarada ou tem o valor undefined , use o operador typeof .

 if (typeof myVar != 'undefined') 

O operador typeof tem garantia de retornar uma string. Comparações diretas contra undefined são problemáticas, pois undefined pode ser sobrescrito.

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

Como apontado pelo @CMS, isso foi corrigido no ECMAScript 5th ed., E o undefined é não-gravável.

if (window.myVar) também includeá esses valores falsos, por isso não é muito robusto:

 falso
 0
 ""
 NaN
 nulo
 Indefinido

Obrigado ao @CMS por apontar que seu terceiro caso – if (myVariable) também pode gerar um erro em dois casos. O primeiro é quando a variável não foi definida, o que gera um ReferenceError .

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

O outro caso é quando a variável foi definida, mas tem uma function getter que gera um erro quando invocada. Por exemplo,

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

Eu pessoalmente uso

 myVar === undefined 

Atenção: Por favor note que === é usado sobre == e que myVar foi previamente declarado (não definido ).


Eu não gosto de typeof myVar === "undefined" . Eu acho que é longo e desnecessário. (Eu posso fazer o mesmo em menos código.)

Agora, algumas pessoas se arrependerão de dor quando lerem isto, gritando: “Espere! WAAITTT !!! undefined pode ser redefinido!”

Legal. Eu sei isso. Então, novamente, a maioria das variables ​​em Javascript pode ser redefinida. Você nunca deve usar um identificador interno que possa ser redefinido?

Se você seguir esta regra, bom para você: você não é um hipócrita.

A questão é que, para fazer muito trabalho real no JS, os desenvolvedores precisam confiar em identificadores redefiníveis para serem o que são. Eu não ouço as pessoas me dizendo que eu não deveria usar setTimeout porque alguém pode

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

Bottom line, o argumento “pode ​​ser redefinido” para não usar um raw === undefined é falso.

(Se você ainda está com medo de undefined ser redefinido, por que você está cegamente integrando código de biblioteca não testado em sua base de código? Ou ainda mais simples: uma ferramenta de lintagem).


Além disso, assim como o typeof abordagem, essa técnica pode “detectar” variables ​​não declaradas:

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

Mas essas duas técnicas vazam em sua abstração. Eu recomendo que você não use isso ou mesmo

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

Considerar:

 var iAmUndefined; 

Para saber se essa variável é declarada ou não, talvez seja necessário recorrer ao operador in . (Em muitos casos, você pode simplesmente ler o código O_o).

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

Mas espere! Tem mais! E se alguma magia de cadeia de protótipos estiver acontecendo…? Agora até o superior in operador não é suficiente. (Ok, eu terminei aqui sobre esta parte, exceto para dizer que 99% do tempo, === undefined (e **** tosse **** typeof ) funciona muito bem. Se você realmente se importa, você pode leia sobre este assunto por conta própria.

Usar typeof é minha preferência. Ele funcionará quando a variável nunca foi declarada, diferente de qualquer comparação com os operadores == ou === ou coerção de tipo usando if . ( undefined , ao contrário de null , também pode ser redefinido em ambientes ECMAScript 3, tornando-o não confiável para comparação, embora quase todos os ambientes comuns agora estejam em conformidade com o ECMAScript 5 ou superior).

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

Você precisa usar typeof .

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

Se estiver indefinido, não será igual a uma string que contenha os caracteres “indefinidos”, pois a string não é indefinida.

Você pode verificar o tipo da variável:

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

Às vezes você nem precisa checar o tipo. Se o valor da variável não puder ser avaliado como falso quando estiver definido (por exemplo, se for uma function), você poderá apenas avaliar a variável. Exemplo:

 if (something) { something(param); } 

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

(Observe que o uso de var in testes faz diferença quando em um wrapper com escopo)

Código para 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 
 if (typeof foo == 'undefined') { // Do something }; 

Note que a comparação estrita ( !== ) não é necessária neste caso, já que typeof sempre retornará uma string.

Neste artigo eu li que frameworks como Underscore.js usam esta function:

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

A maneira mais confiável que eu sei de verificar se há undefined é usar void 0 .

Isso é compatível com navegadores mais novos e antigos, e não pode ser sobrescrito como window.undefined pode, em alguns casos.

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

Pessoalmente, eu sempre uso o seguinte:

 var x; if( x === undefined) { //Do something here } else { //Do something else here } 

A propriedade window.undefined é não-gravável em todos os navegadores modernos (JavaScript 1.8.5 ou posterior). Da documentação da Mozilla: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined , eu vejo isto: Uma razão para usar typeof () é que ele não lança um erro se a variável não foi definida.

Eu prefiro ter a abordagem de usar

 x === undefined 

porque falha e explode na minha cara, em vez de passar / falhar silenciosamente, se x não foi declarado antes. Isso me alerta que x não está declarado. Eu acredito que todas as variables ​​usadas no JavaScript devem ser declaradas.

Atualização 2018-07-25

Já se passaram quase cinco anos desde que este post foi criado, e o JavaScript já percorreu um longo caminho. Ao repetir os testes no post original, não encontrei nenhuma diferença consistente entre os seguintes methods de teste:

  • abc === undefined
  • abc === void 0
  • typeof abc == 'undefined'
  • typeof abc === 'undefined'

Mesmo quando eu modifiquei os testes para evitar que o Chrome os otimizasse, as diferenças foram insignificantes. Como tal, eu recomendaria agora abc === undefined para maior clareza.

Conteúdo relevante do chrome://version :

  • Google Chrome: 67.0.3396.99 (compilation oficial) (64 bits) (coorte: estável)
  • Revisão: a337fbf3c2ab8ebc6b64b0bfdce73a20e2e2252b-refs / branch-heads / 3396 @ {# 790}
  • SO: Windows
  • JavaScript: V8 6.7.288.46
  • User Agent: Mozilla / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36 (KHTML, como o Gecko) Chrome / 67.0.3396.99 Safari / 537.36

Postagem original 2013-11-01

No Google Chrome, o seguinte foi sempre um pouco mais rápido do que um teste de tipo:

 if (abc === void 0) { // Undefined } 

A diferença foi insignificante. No entanto, esse código é mais conciso e mais claro para quem sabe o que significa void 0 . Note, no entanto, que abc ainda deve ser declarado.

Ambos typeof e void foram significativamente mais rápidos do que comparando diretamente com undefined . Usei o seguinte formato de teste no console do desenvolvedor do Google Chrome:

 var abc; start = +new Date(); for (var i = 0; i < 10000000; i++) { if (TEST) { void 1; } } end = +new Date(); end - start; 

Os resultados foram os seguintes:

 Test: | abc === undefined abc === void 0 typeof abc == 'undefined' ------+--------------------------------------------------------------------- x10M | 13678 ms 9854 ms 9888 ms x1 | 1367.8 ns 985.4 ns 988.8 ns 

Observe que a primeira linha está em mili segundos, enquanto a segunda linha está em nano segundos. Uma diferença de 3,4 nanossegundos não é nada. Os tempos foram bastante consistentes nos testes subsequentes.

Como nenhuma das outras respostas me ajudou, sugiro fazer isso. Funcionou para mim no Internet Explorer 8:

 if (typeof variable_name.value === 'undefined') { // variable_name is undefined } 
 // x has not been defined before if (typeof x === 'undefined') { // Evaluates to true without errors. // These statements execute. } if (x === undefined) { // Throws a ReferenceError } 

Ao contrário da resposta do @Thomas Eding:

Se eu esquecer de declarar myVar no meu código, então eu vou pegar myVar is not defined .

Vamos dar um exemplo real:

Eu tenho um nome de variável, mas não tenho certeza se ele está declarado em algum lugar ou não.

Então a resposta do @ Anurag ajudará:

 var myVariableToCheck = 'myVar'; if (window[myVariableToCheck] === undefined) console.log("Not declared or declared, but undefined."); // Or you can check it directly if (window['myVar'] === undefined) console.log("Not declared or declared, but undefined."); 
  var x; if (x === undefined) { alert ("I am declared, but not defined.") }; if (typeof y === "undefined") { alert ("I am not even declared.") }; /* One more thing to understand: typeof ==='undefined' also checks for if a variable is declared, but no value is assigned. In other words, the variable is declared, but not defined. */ // Will repeat above logic of x for typeof === 'undefined' if (x === undefined) { alert ("I am declared, but not defined.") }; /* So typeof === 'undefined' works for both, but x === undefined only works for a variable which is at least declared. */ /* Say if I try using typeof === undefined (not in quotes) for a variable which is not even declared, we will get run a time error. */ if (z === undefined) { alert ("I am neither declared nor defined.") }; // I got this error for z ReferenceError: z is not defined 

Eu uso isso como um parâmetro de function e o excluo na execução da function dessa forma eu obtenho o “real” indefinido. Embora exija que você coloque seu código dentro de uma function. Eu encontrei isso ao ler a fonte jQuery.

 undefined = 2; (function (undefined) { console.log(undefined); // prints out undefined // and for comparison: if (undeclaredvar === undefined) console.log("it works!") })() 

Claro que você poderia apenas usar typeof embora. Mas todo o meu código é geralmente dentro de uma function de contenção de qualquer maneira, então usar este método provavelmente me salva alguns bytes aqui e ali.