# Scope, hoisting and closures

*JavaScript Developer Study Guide · Objects, Functions, and Classes · Last updated October 16, 2026 · https://www.certifyforce.com/study-guide/javascript-developer/objects-functions-and-classes/scope-hoisting-and-closures*

How JavaScript resolves a name through the lexical scope chain, what hoisting does to function declarations, var and let, how closures keep variables alive, and how calls, returns, recursion, switch fall-through and break/continue decide the order of output.

- Certification: Salesforce JavaScript Developer
- Exam section: Objects, Functions, and Classes
- Study guide: https://www.certifyforce.com/study-guide/javascript-developer

**Official exam objective:**

> Given a block of code, analyze the variable scope and the execution flow.

## What the exam expects

- Trace which variable a name resolves to through nested and shadowing scopes, and which names are visible at a given line.
- Predict what happens when a function declaration, a `var` function expression or a `let`/`const` binding is used before its line, including `typeof` checks.
- Read closures that capture variables: factories with independent state, counters, and closures that see later reassignments.
- Trace execution order through nested calls, recursion, `return`, `switch` fall-through, `break` and `continue`.
- Tell which top-level declarations become global object properties in a classic script versus a module.
- Key terms: **lexical scope** (a function sees the scopes where it is written, not where it is called); **scope chain** (the inside-out list of scopes searched for a name); **shadowing** (an inner declaration hiding an outer one with the same name); **hoisting** (declarations taking effect before their line runs); **closure** (a function plus the variables of the scope where it was created); **call stack** (last-in-first-out frames of running functions).

## Key facts

| Fact | Detail | Source |
|---|---|---|
| Lookup direction | Inner scopes see outer ones, never the reverse | [Scope](https://developer.mozilla.org/en-US/docs/Glossary/Scope) |
| Name conflicts | The innermost declaration wins | [Functions (JavaScript Guide)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions) |
| Function declaration | Hoisted with its body; callable anywhere in scope | [function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function) |
| `var` before its line | Reads `undefined` | [Grammar and types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types) |
| `let`/`const`/`class` before their line | ReferenceError (temporal dead zone) | [Hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting) |
| `typeof` undeclared name | `"undefined"`, no error | [typeof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) |
| Undeclared assignment in strict mode | Throws instead of creating a global | [Strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) |
| Top-level `var` in a classic script | Becomes a global object property; not in modules | [var](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var) |
| Top-level `let` | No property on `globalThis` | [let](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) |
| `switch` body | One block shared by all cases | [let](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) |
| Missing `break` | Falls through to later cases, including `default` | [switch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch) |
| Factory closures | Each call has its own lexical environment | [Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures) |

## Check yourself

- Why does a function returned from `outer()` still read `outer`'s variable when called from another function with a same-named variable?
- When does `typeof x` throw?
- Why does calling a `var` function expression above its line throw a TypeError rather than a ReferenceError?
- What does a `switch` do after a matching case that has no `break`?
- Which declarations at the top of a classic script become properties of `window`?

## Sources

- [Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures)
- [Grammar and types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types)
- [Functions (JavaScript Guide)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions)
- [Scope](https://developer.mozilla.org/en-US/docs/Glossary/Scope)
- [Hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
- [function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)
- [typeof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof)
- [let](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)
- [var](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var)
- [Strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)
- [switch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch)
- [break](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break)
- [continue](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue)
- [return](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return)
- [JavaScript execution model](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Execution_model)

## About the full unit

The "Core concepts", "Exam traps" and "Worked scenario" sections of this unit, its 17 linked practice questions, and unlimited timed mock exams are included with the JavaScript Developer pack (USD $19): https://www.certifyforce.com/practice-exams
