JavaScript é a linguagem que dá vida à página, mas tem armadilhas que pegam todo iniciante: por que 0 == '' é verdadeiro? Por que uma variável "vaza" para fora do bloco? Dominar tipos, escopo e o DOM é o que transforma código que funciona por acaso em código que você entende.
Tipos: primitivos vs referência
Valores primitivos (number, string, boolean, null, undefined, symbol, bigint) são copiados por valor. Já objetos, arrays e funções são manipulados por referência: a variável guarda um endereço, não o conteúdo. Pense num primitivo como um bilhete escrito; copiar é reescrever. Um objeto é um endereço de casa; copiar a variável é só anotar o mesmo endereço — as duas apontam para a mesma casa.
let a = 1; let b = a; b = 2;
// a continua 1 (cópia de valor)
let o = { n: 1 }; let p = o; p.n = 2;
// o.n agora é 2 (mesma referência)
== vs === e coerção
O == faz coerção: tenta converter os tipos antes de comparar, gerando surpresas como 0 == '' ou null == undefined serem true. O === compara valor e tipo, sem conversão. A regra de ouro: use sempre ===.
0 == ''; // true (coerção!)
0 === ''; // false (tipos diferentes)
'5' == 5; // true
'5' === 5; // false
var, let, const: escopo e hoisting
let e const têm escopo de bloco (vivem entre { }); var tem escopo de função e "vaza". O hoisting é o JS "içar" declarações para o topo do escopo: var é içada como undefined, enquanto let/const ficam numa "zona morta temporal" e dão erro se acessadas antes da declaração. Prefira const, use let quando precisar reatribuir, e evite var.
| var | let | const | |
|---|---|---|---|
| Escopo | Função | Bloco | Bloco |
| Reatribuível | Sim | Sim | Não |
| Hoisting | undefined | Zona morta | Zona morta |
Closures: a função que lembra
Uma closure acontece quando uma função "lembra" das variáveis do escopo onde foi criada, mesmo depois que esse escopo terminou. É como uma mochila que a função carrega com o ambiente dela dentro.
function contador() {
let n = 0;
return () => ++n;
}
const c = contador();
c(); // 1
c(); // 2 (lembra de n)
O DOM: a página como árvore
O DOM (Document Object Model) é a representação da sua página HTML como uma árvore de objetos que o JavaScript pode ler e alterar. Cada tag vira um nó; você seleciona nós e muda texto, classes, atributos. Não é o HTML em si — é a versão viva dele na memória do navegador.
const btn = document.querySelector('#salvar');
btn.textContent = 'Salvar agora';
Eventos: reagindo ao usuário
O usuário clica, digita, rola — e o JS reage via eventos. Você registra um "ouvinte" e ele dispara quando o evento acontece.
btn.addEventListener('click', () => {
console.log('cliquei!');
});
Tipos, escopo e closures não são curiosidades acadêmicas: são exatamente o que explica os bugs mais comuns de quem está começando.
É comum em entrevista pedir para você prever a saída de uma comparação com ==, explicar o que é uma closure ou diferenciar valor de referência. No dia a dia, isso aparece quando um array "muda sozinho" (era a mesma referência) ou um setTimeout dentro de um loop imprime o número errado.
Conclusão
Entender que primitivos copiam e objetos referenciam, sempre comparar com ===, respeitar o escopo de bloco e enxergar o DOM como árvore — esse é o alicerce do JS. Com closures no bolso, você já está pronto para o passo que confunde até gente experiente: o event loop.
JavaScript is the language that brings the page to life, but it has traps that catch every beginner: why is 0 == '' true? Why does a variable "leak" out of its block? Mastering types, scope and the DOM is what turns code that works by accident into code you understand.
Types: primitives vs reference
Primitive values (number, string, boolean, null, undefined, symbol, bigint) are copied by value. Objects, arrays and functions, on the other hand, are handled by reference: the variable holds an address, not the content. Think of a primitive as a written note; copying it means rewriting it. An object is a house address; copying the variable just means jotting down the same address — both point to the same house.
let a = 1; let b = a; b = 2;
// a is still 1 (value copy)
let o = { n: 1 }; let p = o; p.n = 2;
// o.n is now 2 (same reference)
== vs === and coercion
== performs coercion: it tries to convert the types before comparing, producing surprises like 0 == '' or null == undefined being true. === compares value and type, with no conversion. The golden rule: always use ===.
0 == ''; // true (coercion!)
0 === ''; // false (different types)
'5' == 5; // true
'5' === 5; // false
var, let, const: scope and hoisting
let and const are block-scoped (they live between { }); var is function-scoped and "leaks". Hoisting is JS "lifting" declarations to the top of the scope: var is hoisted as undefined, while let/const sit in a "temporal dead zone" and throw an error if accessed before the declaration. Prefer const, use let when you need to reassign, and avoid var.
| var | let | const | |
|---|---|---|---|
| Scope | Function | Block | Block |
| Reassignable | Yes | Yes | No |
| Hoisting | undefined | Dead zone | Dead zone |
Closures: the function that remembers
A closure happens when a function "remembers" the variables from the scope where it was created, even after that scope has finished. It's like a backpack the function carries with its environment inside.
function contador() {
let n = 0;
return () => ++n;
}
const c = contador();
c(); // 1
c(); // 2 (remembers n)
The DOM: the page as a tree
The DOM (Document Object Model) is the representation of your HTML page as a tree of objects that JavaScript can read and change. Each tag becomes a node; you select nodes and change text, classes, attributes. It's not the HTML itself — it's the live version of it in the browser's memory.
const btn = document.querySelector('#salvar');
btn.textContent = 'Salvar agora';
Events: reacting to the user
The user clicks, types, scrolls — and JS reacts through events. You register a "listener" and it fires when the event happens.
btn.addEventListener('click', () => {
console.log('cliquei!');
});
Types, scope and closures aren't academic curiosities: they are exactly what explains the most common bugs for people just starting out.
Interviews commonly ask you to predict the output of a == comparison, explain what a closure is or tell value from reference. Day to day, it shows up when an array "changes by itself" (it was the same reference) or a setTimeout inside a loop prints the wrong number.
Conclusion
Understanding that primitives copy and objects reference, always comparing with ===, respecting block scope and seeing the DOM as a tree — that's the foundation of JS. With closures in your pocket, you're ready for the step that confuses even experienced people: the event loop.