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.