404 Not Found

404 Not Found


nginx

Tipos de Dados em JavaScript

Tipos de dados determinam quais operações você pode realizar — números suportam aritmética, strings suportam concatenação, booleanos suportam condicionais. Entender tipos ajuda a evitar as armadilhas mais clássicas do JS.

Tipos de Dados do JS

JavaScript tem 8 tipos de dados, divididos em primitivos e tipos de referência:

Primitivos (7 tipos): String, Number, BigInt, Boolean, Undefined, Null, Symbol

Tipo de referência (1 tipo): Object (arrays, funções, datas, etc. são todos subtipos de Object)

Dados primitivos são armazenados na memória stack e copiados por valor durante a atribuição. Dados de tipo de referência são armazenados na memória heap e copiados por referência (endereço) durante a atribuição. Essa distinção será abordada em profundidade em lições posteriores.

O Operador typeof

typeof é um operador que verifica tipos de dados e retorna uma string:

Valor Resultado do typeof
"olá" "string"
42 "number"
9007199254740991n "bigint"
true "boolean"
undefined "undefined"
null "object" (bug histórico)
{ } "object"
function(){} "function"

Nota: typeof null retorna "object" — este é um bug histórico desde o início do JS que nunca pode ser corrigido (mudar isso quebraria código existente). Apenas lembre-se.

Armadilhas de String e Number

O operador + no JS serve para dois propósitos: adição numérica e concatenação de strings. Quando um lado do + é uma string, JS converte o outro valor para string também:

Esta é uma das armadilhas mais clássicas do JS — todo iniciante cai nela. A solução: use Number() ou parseInt() para conversão explícita antes de operações matemáticas.

null vs undefined

Ambos significam "sem valor", mas diferem na intenção:

Pense assim: undefined é uma casa nova sem móveis ainda; null é quando você deliberadamente tirou todos os móveis.

Exemplo: typeof com Vários Tipos

HTML
<!DOCTYPE html>
<html lang="pt-br">
<head>
  <meta charset="UTF-8">
  <title>Tipos de Dados JS - typeof</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 600px; margin: 60px auto; }
    table { width: 100%; border-collapse: collapse; margin: 16px 0; }
    th, td { padding: 10px; text-align: left; border: 1px solid #ddd; }
    th { background: #2196F3; color: #fff; }
    button { margin-top: 12px; padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #2196F3; }
    #result { margin-top: 12px; padding: 16px; background: #f5f5f5; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; white-space: pre; }
  </style>
</head>
<body>
  <h2>Operador typeof</h2>
  <button id="testBtn">Executar Teste typeof</button>
  <div id="result">Clique no botão para ver os resultados do typeof</div>
  <script>
    document.getElementById("testBtn").onclick = function() {
      var a = "olá";
      var b = 42;
      var c = 9007199254740991n;
      var d = true;
      var e = undefined;
      var f = null;
      var g = {name: "João"};
      var h = [1, 2, 3];
      var i = function(){};
      var output = "";
      output += 'typeof "olá"    → "' + typeof a + '"\n';
      output += "typeof 42       → \"" + typeof b + '"\n';
      output += "typeof 9007199254740991n → \"" + typeof c + '"\n';
      output += "typeof true     → \"" + typeof d + '"\n';
      output += "typeof undefined → \"" + typeof e + '"\n';
      output += "typeof null     → \"" + typeof f + '"  ⚠️ Bug histórico!\n';
      output += "typeof {}       → \"" + typeof g + '"\n';
      output += "typeof []       → \"" + typeof h + '"  (arrays também são objeto)\n';
      output += 'typeof function → "' + typeof i + '"';
      document.getElementById("result").textContent = output;
    };
  </script>
</body>
</html>
▶ Experimente

Exemplo: Armadilhas de String e Number

HTML
<!DOCTYPE html>
<html lang="pt-br">
<head>
  <meta charset="UTF-8">
  <title>Tipos de Dados JS - Armadilha String vs Number</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 550px; margin: 60px auto; }
    .trap { background: #fff3e0; padding: 12px; border-radius: 8px; color: #E65100; border-left: 4px solid #FF9800; margin: 12px 0; }
    .safe { background: #e8f5e9; padding: 12px; border-radius: 8px; color: #2E7D32; border-left: 4px solid #4CAF50; margin: 12px 0; }
    .row { display: flex; justify-content: space-between; padding: 10px 16px; border-bottom: 1px solid #eee; font-family: Consolas, monospace; }
    .row:last-child { border-bottom: none; }
    .result-box { background: #f5f5f5; border-radius: 8px; margin: 12px 0; overflow: hidden; }
    .label { color: #666; }
    .value { font-weight: bold; }
    .bad { color: #f44336; }
    .good { color: #4CAF50; }
    button { margin-top: 12px; padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #e91e63; }
  </style>
</head>
<body>
  <h2>Armadilha de String + Number</h2>
  <p class="trap">⚠️ Quando + tem uma string em qualquer lado, JS concatena em vez de somar! "5"+3 dá "53", não 8</p>
  <button id="trapBtn">Executar Demonstração da Armadilha</button>
  <div class="result-box" id="trapResult">
    <div class="row"><span class="label">"5" + 3 =</span><span class="value" id="r1">?</span></div>
    <div class="row"><span class="label">5 + 3 =</span><span class="value" id="r2">?</span></div>
    <div class="row"><span class="label">"5" - 3 =</span><span class="value" id="r3">?</span></div>
    <div class="row"><span class="label">"5" * 3 =</span><span class="value" id="r4">?</span></div>
  </div>
  <p class="safe">✅ Solução: use Number() para conversão explícita antes de operações aritméticas</p>
  <button id="safeBtn" style="background:#4CAF50;">Executar Versão Segura</button>
  <div class="result-box" id="safeResult">
    <div class="row"><span class="label">Number("5") + 3 =</span><span class="value" id="s1">?</span></div>
  </div>
  <script>
    document.getElementById("trapBtn").onclick = function() {
      var r1 = "5" + 3;
      var r2 = 5 + 3;
      var r3 = "5" - 3;
      var r4 = "5" * 3;
      document.getElementById("r1").textContent = '"' + r1 + '"';
      document.getElementById("r1").className = "value bad";
      document.getElementById("r2").textContent = r2;
      document.getElementById("r2").className = "value good";
      document.getElementById("r3").textContent = r3;
      document.getElementById("r3").className = "value good";
      document.getElementById("r4").textContent = r4;
      document.getElementById("r4").className = "value good";
    };
    document.getElementById("safeBtn").onclick = function() {
      var s1 = Number("5") + 3;
      document.getElementById("s1").textContent = s1;
      document.getElementById("s1").className = "value good";
    };
  </script>
</body>
</html>
▶ Experimente

Exemplo: null vs undefined

HTML
<!DOCTYPE html>
<html lang="pt-br">
<head>
  <meta charset="UTF-8">
  <title>Tipos de Dados JS - null vs undefined</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 550px; margin: 60px auto; }
    .card { padding: 16px; border-radius: 8px; margin: 12px 0; }
    .undef { background: #e3f2fd; border-left: 4px solid #2196F3; }
    .nul { background: #f3e5f5; border-left: 4px solid #9C27B0; }
    .result { background: #f5f5f5; padding: 16px; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; white-space: pre; margin: 12px 0; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #9C27B0; margin: 6px; }
  </style>
</head>
<body>
  <h2>null vs undefined</h2>
  <div class="card undef">
    <strong>undefined</strong>: variável declarada mas não atribuída, ou propriedade não existe<br>
    Significado: "nenhum valor dado ainda" — como uma casa nova sem móveis
  </div>
  <div class="card nul">
    <strong>null</strong>: desenvolvedor explicitamente definiu como vazio<br>
    Significado: "intencionalmente definido como nada" — você deliberadamente tirou os móveis
  </div>
  <button id="testBtn">Executar Teste de Comparação</button>
  <div class="result" id="output">Clique no botão para ver os resultados</div>
  <script>
    document.getElementById("testBtn").onclick = function() {
      var a;
      var b = null;
      var c = {name: "João"};
      var output = "";
      output += "=== Casos de undefined ===\n";
      output += "var a;  → a = " + a + " (undefined)\n";
      output += "typeof a → \"" + typeof a + "\"\n";
      output += "c.idade → " + c.age + " (propriedade inexistente também é undefined)\n\n";
      output += "=== Casos de null ===\n";
      output += "var b = null;  → b = " + b + " (null)\n";
      output += "typeof b → \"" + typeof b + "\"  ⚠️ Bug histórico\n\n";
      output += "=== Comparação ===\n";
      output += "null == undefined  → " + (null == undefined) + "  (igualdade frouxa)\n";
      output += "null === undefined → " + (null === undefined) + "  (desigualdade estrita)\n";
      output += "typeof null  → \"object\"  (bug)\n";
      output += "typeof undefined → \"undefined\"  (correto)\n\n";
      output += "Conclusão: null === undefined é false\n";
      output += "Eles têm significados diferentes e não são o mesmo valor sob comparação estrita";
      document.getElementById("output").textContent = output;
    };
  </script>
</body>
</html>
▶ Experimente

Exemplo: Todos os Tipos de Dados de Uma Vez

HTML
<!DOCTYPE html>
<html lang="pt-br">
<head>
  <meta charset="UTF-8">
  <title>Tipos de Dados JS - Visão Completa</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 600px; margin: 60px auto; }
    .type-card { display: inline-block; width: 120px; padding: 16px; margin: 6px; border-radius: 10px; text-align: center; color: #fff; cursor: pointer; transition: transform 0.2s; }
    .type-card:hover { transform: scale(1.08); }
    .type-card h3 { margin: 0 0 4px; font-size: 14px; opacity: 0.9; }
    .type-card p { margin: 0; font-size: 12px; font-family: Consolas, monospace; }
    .string { background: #4CAF50; }
    .number { background: #2196F3; }
    .bigint { background: #e91e63; }
    .boolean { background: #FF9800; }
    .undef { background: #9E9E9E; }
    .nul { background: #795548; }
    .symbol { background: #00BCD4; }
    .object { background: #9C27B0; }
    #detail { margin-top: 20px; padding: 20px; background: #f5f5f5; border-radius: 8px; font-size: 16px; line-height: 1.8; display: none; }
  </style>
</head>
<body>
  <h2>8 Tipos de Dados do JS</h2>
  <div class="type-card string" onclick="showDetail('string')"><h3>String</h3><p>"olá"</p></div>
  <div class="type-card number" onclick="showDetail('number')"><h3>Number</h3><p>42</p></div>
  <div class="type-card bigint" onclick="showDetail('bigint')"><h3>BigInt</h3><p>900n</p></div>
  <div class="type-card boolean" onclick="showDetail('boolean')"><h3>Boolean</h3><p>true</p></div>
  <div class="type-card undef" onclick="showDetail('undefined')"><h3>Undefined</h3><p>undefined</p></div>
  <div class="type-card nul" onclick="showDetail('null')"><h3>Null</h3><p>null</p></div>
  <div class="type-card symbol" onclick="showDetail('symbol')"><h3>Symbol</h3><p>Symbol()</p></div>
  <div class="type-card object" onclick="showDetail('object')"><h3>Object</h3><p>{chave:"val"}</p></div>
  <div id="detail"></div>
  <script>
    function showDetail(type) {
      var detailEl = document.getElementById("detail");
      detailEl.style.display = "block";
      var info = {
        "string": "String\nTexto entre aspas: \"olá\", 'mundo'\ntypeof → \"string\"\nPode ser concatenado com +",
        "number": "Number\nInteiros e decimais: 42, 3.14, -7\nValores especiais: Infinity, -Infinity, NaN\ntypeof → \"number\"",
        "bigint": "BigInt\nRepresenta inteiros além do alcance seguro do Number\nSintaxe: adicione n após o número, ex: 9007199254740991n\ntypeof → \"bigint\"",
        "boolean": "Boolean\nApenas dois valores: true e false\nComumente usado em condicionais\ntypeof → \"boolean\"",
        "undefined": "Undefined\nValor padrão para variáveis declaradas mas não atribuídas\ntypeof → \"undefined\"\nSignifica \"nenhum valor ainda\"",
        "null": "Null\nDesenvolvedor define explicitamente como \"vazio\"\ntypeof → \"object\" (bug histórico!)\nnull === undefined é false",
        "symbol": "Symbol\nAdicionado no ES6, cria identificadores únicos\nTodo Symbol() é diferente\ntypeof → \"symbol\"\nComumente usado como chaves de propriedade de objeto",
        "object": "Object\nTipo de referência, armazena pares chave-valor\nArrays [], funções e datas são todos objetos\ntypeof → \"object\""
      };
      detailEl.textContent = info[type];
    }
  </script>
</body>
</html>
▶ Experimente

📖 Resumo

  1. JS tem 8 tipos de dados: 7 primitivos + 1 tipo de referência (Object)
  2. O operador typeof verifica tipos, mas typeof null retorna "object" — um bug histórico
  3. + concatena quando uma string está envolvida — "5" + 3"53", não 8
  4. null significa "intencionalmente vazio"; undefined significa "nenhum valor ainda" — eles não são estritamente iguais
  5. Use Number() ou parseInt() para conversão explícita antes de operações matemáticas para evitar armadilhas de coerção implícita
  6. Arrays [] também retornam "object" do typeof — use Array.isArray() para distinguir arrays de objetos

❓ Perguntas Frequentes

P:Por que typeof null retorna "object"? R:Este é um bug histórico da primeira versão do JS. Naquela época, JS usava bits baixos para identificar tipos, e null tinha todos os bits baixos zero — iguais ao identificador de objeto — então foi classificado incorretamente. Tentaram corrigir depois, mas mudar isso quebraria muito código existente, então o bug se tornou permanente. É como um prédio com fundação torta — muita gente mora lá para demolir.

P:Como verifico se um valor é um array ou um objeto simples? R:typeof retorna "object" tanto para arrays quanto para objetos, então não pode distingui-los. A abordagem correta é Array.isArray() — por exemplo, Array.isArray([1,2]) retorna true, enquanto Array.isArray({}) retorna false.

P:Qual tipo é NaN? R:NaN (Not a Number — Não é um Número) tem typeof NaN retornando "number". Ainda mais estranho, NaN === NaN retorna false — não é nem igual a si mesmo. Use isNaN() ou Number.isNaN() para verificar NaN.

📝 Atividades

  1. Básico: Declare 6 variáveis para 6 tipos primitivos (String, Number, Boolean, Undefined, Null, Object), use typeof em cada uma e exiba os resultados na página.
  2. Intermediário: Crie uma página com um campo de entrada. Quando o usuário inserir qualquer valor, JS detecta seu tipo usando typeof e exibe o resultado. Tente inserir números, strings, true, null, etc., e observe a saída do typeof.
  3. Desafio: Crie uma página de "Quiz de Armadilhas de Tipo" com 5 perguntas de múltipla escolha testando conhecimento de coerção de tipo, como o que "1" + 2 resulta, se null == undefined é true ou false, etc. Mostre feedback correto/incorreto com explicações quando o usuário clicar em uma opção.
100%