typeof! == "indefinido" vs.! = nulo

491

Muitas vezes vejo código JavaScript que verifica parâmetros indefinidos, etc., desta maneira:

if (typeof input !== "undefined") {
    // do stuff
}

Isso parece meio desperdício, pois envolve uma pesquisa de tipo e uma comparação de cadeias, sem mencionar sua verbosidade. É necessário porque undefinedpode ser renomeado, no entanto.

Minha pergunta é:
como esse código é melhor do que essa abordagem:

if (null != input) {
    // do stuff
}

Tanto quanto eu sei, você não pode redefinir null, então não vai quebrar inesperadamente. E, devido à coerção de tipo do !=operador, isso verifica os dois undefinede null... o que geralmente é exatamente o que você deseja (por exemplo, parâmetros de função opcionais).

No entanto, esse formulário não parece generalizado e até faz com que o JSLint grite com você por usar o !=operador incorreto .

Por que isso é considerado um estilo ruim?

Derek Thurn
fonte
13
@ Marcel, não há diferença real, mas há duas razões para fazê-lo. Um é que, para alguns, é mais claro ler. E a segunda razão, é que ela impede a substituição acidental de uma variável. Você já fez isso: if (foo = "value") quando pretendia fazer uma comparação. Se você adquire o hábito de reverter a variável, no operador de atribuição / comparação, não terá esse problema.
Layke 11/10
29
Para alguns (inclusive eu), isso é realmente mais difícil de ler. Além disso, a maioria dos IDEs avisa sobre atribuições acidentais. Mas ainda uso esse formulário se a variável comparada for muito longa. YMMV.
Johndodo 4/04
15
@MarcelKorpel Isso é chamado de "condição Yoda": umumble.com/blogs/Programming/321
kol:
55
É mais difícil de ler. Não se diz "Não está vazia a garrafa".
Noel Abrahams
11
if (null != input)é apenas "Yoda Speak" para o falante de inglês (de um eu sou .... uuammmmm), portanto, se eles equivalem à mesma coisa, é realmente apenas semântica. NA MINHA HUMILDE OPINIÃO.
WebLacky3rdClass

Respostas:

710

typeof é mais seguro, pois permite que o identificador nunca tenha sido declarado antes:

if(typeof neverDeclared === "undefined") // no errors

if(neverDeclared === null) // throws ReferenceError: neverDeclared is not defined
seanmonstar
fonte
3
if ((typeof neverDeclared! == "undefined") && (neverDeclared! == null)) {return true; } else {return false; }
Anthony DiSanti 24/10/10
88
Use === ao comparar com nulo / indefinido.
MyGGaN
47
@MyGGaN apenas se você quiser distinguir entre os dois. Em muitos casos, ==pode ser melhor, porque ele testa nulos e indefinidos.
Seanmonstar
10
Não consigo encontrar nenhuma diferença entre typeof somevar == 'undefined' e typeof somevar === 'undefined', porque typeof sempre retorna string. Para null, retornará 'objeto'. Ou pode ser que eu esteja errado?
TomTom
2
Acredito que o comentário do @ TomTom seja o cerne do problema - não consigo entender por que alguém usaria os operadores !==ou ===ao comparar um valor cujo tipo é conhecido por ser uma string.
Nicolas Rinaudo 30/08
49

Se a variável for declarada (com a varpalavra - chave, como argumento de função ou como variável global), acho que a melhor maneira de fazer isso é:

if (my_variable === undefined)

jQuery faz isso, então é bom o suficiente para mim :-)

Caso contrário, você precisará usar typeofpara evitar a ReferenceError.

Se você espera que o indefinido seja redefinido, você pode agrupar seu código assim:

(function(undefined){
    // undefined is now what it's supposed to be
})();

Ou obtenha-o através do voidoperador:

const undefined = void 0;
// also safe
Joey Adams
fonte
1
Se undefined já tiver sido definido, você não o passaria para sua função anônima através de um parâmetro chamado undefined, sem realizar nada?
Anthony DiSanti
20
@ Anthony DiSanti: Não, undefinedé o nome dado ao parâmetro da função, não o seu valor. Nada é passado para a função, significando que o valor do primeiro parâmetro é indefinido.
Joey Adams
3
Ah, meu erro, obrigado por acompanhar. Eu removi meu voto, desculpe por isso.
Anthony DiSanti
2
Por que escrever uma exceção para lidar com indefinido sendo declarado por outro desenvolvedor quando você pode fazê-lo corretamente para começar? O jQuery agrupa a função anônima inicial, como você mostra na sua função, para garantir que o indefinido não foi definido e para diminuir o tamanho reduzido. Simplificando, se ele pode fornecer resultados inesperados para fazê-lo dessa maneira, por que arriscar uma programação lenta para evitar digitar (typeof variable === 'undefined'). E se desejássemos (typeof variable === 'object') deveríamos fornecer uma variável padrão que também seja um objeto para que possamos fazer (variável === objeto)?
precisa saber é
28

bom caminho:

if(typeof neverDeclared == "undefined") //no errors

Mas a melhor maneira é verificar através de:

if(typeof neverDeclared === typeof undefined) //also no errors and no strings
Piada
fonte
6
var undefined = function () {}; if (typeof neverDeclared === typeof undefined); neverDecalred! = 'function'; jsfiddle.net/hbPZ5 retorna tipo de var; retorna uma string. Sem erros ou seqüências de caracteres, mas nem sempre dará os resultados esperados. Os desenvolvedores concedidos não devem declarar indefinidos, mas existem algumas estruturas e bibliotecas que o fazem.
precisa saber é
1
Eu uso principalmente, if (typeof neverDeclared === typeof undefined) { mas o Lint gera um erro. "Esperava uma string e viu 'typeof'." Como você contornaria esse erro? Devemos nos submeter às demandas de Lint e usar o 'bom caminho'?
Ayelis
2
@fyrye Você conhece alguma biblioteca / framework JavaScript que realmente muda indefinidamente? Eu sei que é possível; mas eu gostaria de encontrar um exemplo selvagem de "Aqui é onde você pode encontrar esse gnus desagradável!"
bigtunacan
4
typeof neverDeclared === typeof void 0;-D
Alex Yaroshevich
1
É propenso a erros, porque na verdade você está apenas confiando em uma determinada variável ("indefinida") que não está sendo definida. O que pode ser falso, como outras postagens mostraram. Você sempre pode fazer, if(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined) {mas é bastante longo.
Pierre-Olivier Vares
12

Você realmente não deve se preocupar em renomear o indefinido. Se alguém renomear indefinido, você terá muito mais problemas do que apenas alguns se as verificações falharem. Se você realmente deseja proteger seu código, envolva-o em uma IFFE (expressão de função imediatamente chamada) assim:

(function($, Backbone, _, undefined) {
    //undefined is undefined here.
})(jQuery, Backbone, _);

Se você estiver trabalhando com variáveis ​​globais (que já estão erradas) em um ambiente de navegador, verifiquei indefinidamente assim:

if(window.neverDefined === undefined) {
    //Code works
}

Como as variáveis ​​globais fazem parte do objeto de janela, você pode simplesmente verificar o indefinido em vez de converter em uma string e comparar as strings.

Além disso, por que suas variáveis ​​não estão definidas? Eu já vi muitos códigos em que eles verificam a existência de variáveis ​​e executam alguma ação com base nisso. Nem uma vez vi onde essa abordagem estava correta.

Peeter
fonte
1
A validação de entrada e a verificação de dependência são boas razões para usar isso. Se eu tiver arquivos Javascript dependentes de outros arquivos carregados ou objetos init declarados, é útil testar objetos ou propriedades de que um arquivo depende indefinidamente e lançar uma boa exceção em vez de deixar seu script falhar em algum lugar imprevisível.
AmericanUmlaut
Parece que você pode precisar de algo nas linhas da AMD (require.js)
Peeter
1
Ou eu poderia apenas querer fazer uma comparação muito simples em vez de incluir outra biblioteca no meu projeto :)
AmericanUmlaut
Tarde demais para editar :(. Queria adicionar - require.js também não é a solução certa para validação de entrada (os objetos init que mencionei no meu comentário inicial). Se você tem um objeto que espera ser preenchido com certos valores antes do script é carregado, então é útil para lançar uma exceção se eles não estão definidos.
AmericanUmlaut
1
Não, porque typeof retorna uma string. Então typeof undefined retorna "undefined". window.input == indefinido (se a variável está no spoce global)!
Peeter
5

Se você está realmente preocupado com a redefinição indefinida, pode se proteger contra isso com algum método auxiliar como este:

function is_undefined(value) {
   var undefined_check; // instantiate a new variable which gets initialized to the real undefined value
   return value === undefined_check;
}

Isso funciona porque quando alguém escreve, undefined = "foo"ele apenas permite que o nome undefined faça referência a um novo valor, mas ele não altera o valor real de undefined.

Ivo Wetzel
fonte
1
No entanto, você introduziu uma chamada de função, o que prejudicará o desempenho.
Tim Baixo
Eu não acho que essa chamada de função prejudique o desempenho, é muito mais provável que o DOM seja o gargalo. De qualquer forma, se você tiver sua grande função anônima habitual que contém sua biblioteca, você também pode definir undefined_checkna parte superior e apenas usá-la em qualquer lugar do seu código.
Ivo Wetzel
1
Concordo e não estou dizendo que isso é uma má idéia. Vale ressaltar que chamar esta função terá um desempenho mais lento do que uma typeofverificação.
Tim Baixo
Eu acho que essa função é simples o suficiente para ser incorporada, para que o desempenho não seja afetado.
huyz 6/09/11
4
@ TimDown: primeiro código de gravação, legível. segundo código de gravação, que pode ser mantido e, se for realmente lento. depois pense em desempenho.
18713 Andreas
4

Você também pode usar o operador void para obter um valor indefinido:

if (input !== void 0) {
    // do stuff    
}

(E sim, como observado em outra resposta, isso gerará um erro se a variável não tiver sido declarada, mas esse caso pode ser descartado com freqüência por inspeção de código ou refatoração de código, por exemplo, usando window.input !== void 0para testar variáveis ​​globais ou adicionar var input.)

Claude
fonte
1

Na verdade, me deparei se (typeof input !== 'undefined')neste cenário em que ele está sendo usado para fornecer parâmetros de função padrão:

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

O ES6 fornece novas maneiras de introduzir parâmetros de função padrão desta maneira:

function greet(name = 'Student', greeting = 'Welcome') {
  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

Isso é menos detalhado e mais limpo que a primeira opção.

JSpecs
fonte
1

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  console.log(greeting,name);
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

//ES6 provides new ways of introducing default function parameters this way:

function greet2(name = 'Student', greeting = 'Welcome') {
//  return '${greeting} ${name}!';
console.log(greeting,name);
}

greet2(); // Welcome Student!
greet2('James'); // Welcome James!
greet2('Richard', 'Howdy'); // Howdy Richard!

Avinash Maurya
fonte
0

(function(){

  var a= b = 3;
  var ed = 103;
  
})();



//console.log(ed); //ed is not defined

console.log("a defined? " + (typeof a !== 'undefined')); //no define
console.log("b defined? " + (typeof b !== 'undefined')); //yes define
console.log(typeof(b)); //number
console.log(typeof(4+7));   //number
console.log(b); //3
console.log(typeof("4"+"7")); //string
var e= "ggg";
console.log(typeof(e)); //string
 var ty=typeof(b);
console.log(ty); //number
console.log(typeof false); //boolean
console.log(typeof 1); //number
console.log(typeof 0); //number
console.log(typeof true); //boolean


console.log(typeof Math.tan);  //function
console.log(typeof function(){}); //function 

if(typeof neverDeclared == "undefined") //no errors
if(typeof neverDeclared === "undefined") //no errors

//if(neverDeclared == null) //showing error 


console.log(typeof {a:1}); //object
console.log(typeof null); //object
console.log(typeof JSON); //object
console.log(typeof Math); //object
console.log(typeof /a-z/); //object
console.log(typeof new Date()); //object

console.log(typeof afbc); //undefined
//console.log(typeof new);//error

document.write("<br> * oprator as math ");
var r=14*"4";
document.write(r);

document.write("<br> + oprator as string ");
var r=14+"44";
document.write(r);

document.write("<br> Minus Operator work as mathematic ");
var r=64-"44";
document.write(r);


document.write("<br>");
console.log(typeof(4*"7")); //returns number
console.log(typeof(4+"7")); //returns string




 
Interview Question in JavaScript

Avinash Maurya
fonte
Você pode fornecer uma explicação?
jhpratt GOFUNDME RELICENSING
Existem seis valores possíveis que typeof retorna: objeto, booleano, função, número, string e indefinido. O operador typeof é usado para obter o tipo de dados (retorna uma string) de seu operando. O operando pode ser uma estrutura literal ou de dados, como uma variável, uma função ou um objeto. O operador retorna o tipo de dados. Sintaxe typeof operando ou typeof (operando)
Avinash Maurya
0

var bar = null;
console.log(typeof bar === "object"); //true yes 
//because null a datatype of object

var barf = "dff";
console.log(typeof barf.constructor);//function


console.log(Array.isArray(bar));//falsss


console.log((bar !== null) && (bar.constructor === Object)); //false

console.log((bar !== null) && (typeof bar === "object"));  // logs false
//because bar!==null, bar is a object


console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function"))); //false

console.log(typeof bar === typeof object); //false
console.log(typeof bar2 === typeof undefined); //true
console.log(typeof bar3 === typeof undefinedff); //true
console.log(typeof bar2 == typeof undefined); //true

console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]")); //false

Avinash Maurya
fonte
-7
if (input == undefined) { ... }

funciona muito bem. Obviamente, não é uma nullcomparação, mas geralmente acho que, se preciso distinguir entre undefinede null, na verdade, preciso distinguir entre undefinede qualquer valor falso, então

else if (input) { ... }

faz isso.

Se um programa redefine, undefinedele é realmente muito interessante.

A única razão pela qual consigo pensar foi na compatibilidade com o IE4, ela não entendeu a undefinedpalavra - chave (que não é realmente uma palavra-chave, infelizmente), mas é claro que os valores poderiam ser undefined , então você precisava disso:

var undefined;

e a comparação acima funcionaria bem.

No seu segundo exemplo, você provavelmente precisará de parênteses duplos para deixar o fiapo feliz?

UniquePhoton
fonte
Você input == undefinedretornará trueem uma nullentrada.
mgol 30/07/12