Introdução: por que seu código falha com o erro "undefined"?
\n\nVocê escreve código, tudo parece lógico, mas de repente — TypeError: Cannot read properties of undefined. Familiar? Esse erro é um verdadeiro pesadelo para iniciantes e um visitante frequente no Stack Overflow. O tópico "Detecting an undefined object property" acumulou milhares de visualizações, e não é por acaso.
\n\nObjetos em JavaScript são como caixas de surpresas. Você nunca sabe ao certo se a propriedade que precisa está lá dentro, especialmente se o objeto veio de uma API, banco de dados ou de outro desenvolvedor. Hoje, vamos nos tornar verdadeiros detetives e analisar todas as formas de pegar o undefined em flagrante. Você aprenderá a diferença entre undefined e null, quando usar typeof e quando usar hasOwnProperty, e como o JavaScript moderno simplifica nossa vida.
Vamos nessa! 🚀
\n\nO que é undefined na verdade?
\n\nAntes de capturar o undefined, vamos entender o que é essa fera. Em JavaScript, undefined é um valor primitivo que é atribuído automaticamente a uma variável se nenhum valor for definido para ela. Mas com objetos, a coisa é mais complicada.
Uma propriedade de objeto pode ser undefined em dois casos:
- \n
- A propriedade existe, mas seu valor foi explicitamente definido como
undefined. \n - A propriedade não existe no objeto. \n
E é aqui que a coisa fica interessante. Para o código externo, esses dois casos parecem iguais: ao tentar ler uma propriedade inexistente, você obtém undefined. Mas para sua lógica, a diferença pode ser crítica.
const user = {\n name: 'Ana',\n age: undefined, // propriedade existe, mas valor é undefined\n // city: não declarado\n};\n\nconsole.log(user.age); // undefined\nconsole.log(user.city); // undefined\n\nAmbas as chamadas retornarão undefined, mas a primeira porque foi definida assim, a segunda porque a propriedade não existe. Como diferenciar? Continue lendo.
Método 1: Operador typeof — o bom e velho método
\n\nA maneira mais simples e segura de verificar uma propriedade é usar typeof. Este operador nunca lança um erro, mesmo se você acessar uma propriedade inexistente.
const book = {\n title: 'O Mestre e Margarida',\n author: 'Bulgakov'\n};\n\nif (typeof book.year !== 'undefined') {\n console.log('Ano de publicação:', book.year);\n} else {\n console.log('Propriedade year não encontrada');\n}\n// Saída: Propriedade year não encontrada\n\nVantagens: Seguro, funciona em todos os navegadores, não requer métodos adicionais.
\nDesvantagens: Não diferencia a situação em que a propriedade existe, mas é igual a undefined. Se book.year = undefined, typeof ainda mostrará 'undefined'.
Quando usar typeof?
\nIdeal para verificações rápidas, quando você só precisa evitar um erro e a diferença sutil entre "propriedade existe, mas é undefined" e "propriedade não existe" não é importante. Particularmente útil para variáveis globais.
\n\nMétodo 2: Operador in — detetor de existência
\n\nO operador in verifica se uma propriedade existe no objeto, incluindo propriedades herdadas. Ele retorna true ou false dependendo se a propriedade está na cadeia de protótipos.
const car = {\n brand: 'Tesla',\n model: 'Model 3'\n};\n\nconsole.log('brand' in car); // true\nconsole.log('year' in car); // false\nconsole.log('toString' in car); // true (herdado de Object.prototype)\n\nObserve: in retornará true mesmo se a propriedade for igual a undefined:
const config = {\n debug: undefined\n};\n\nconsole.log('debug' in config); // true — a propriedade existe