Quick Overview
A variable resolves by where the function was written, never where it was called. The lookup walks outward through each enclosing scope and throws `ReferenceError` only on reaching global empty-handed.
Scope determines where variables are accessible in your code. Lexical Environment refers to where code is physically written in your script hierarchy.
When a function accesses a variable, JavaScript searches its local scope first. If not found, it travels UP the Scope Chain to parent scopes until it reaches the Global Scope.
Outer scopes cannot look inside inner function scopes, but inner functions have full access to their parent lexical environments:
[ Global Scope ] -> globalVar = "Global"
^
| (Searches Upward)
[ Outer Function ] -> outerVar = "Outer Scope"
^
| (Searches Upward)
[ Inner Function ] -> localVar = "Local"
const globalName = "DevLoom";
function outer() {
const outerVar = "Outer Scope";
function inner() {
// Searches local -> Outer -> Global
console.log(`${globalName} | ${outerVar}`);
}
inner();
}
outer(); // Output: "DevLoom | Outer Scope"
JavaScript uses Lexical Scoping (Static Scoping). This means variable resolution depends on where functions are defined in the source code, NOT where they are called from!
const, let, or var inside a function (e.g. score = 100) implicitly attaches it to the global window object in non-strict mode.Write it yourself. The tests below run against your code.
Keep variables tightly scoped inside functions. Next, let's explore Block Scope and the Temporal Dead Zone (TDZ)!
Primitives copy by value and objects copy by reference, so `b = a` duplicates a number but shares an object. That single distinction explains most surprise mutations in a codebase.
`const` prevents reassignment, not mutation: a `const` object's properties can still be changed. `let` is scoped to its block, while `var` is function-scoped and leaks out of loops.
Only backticks interpolate: `${user}` reads the variable, while the identical text in quotes prints literally. Strings are immutable, so every method returns a new one rather than editing in place.