Skip to main content

Scope in JavaScript

Scope is the mechanism in JavaScript that defines where in the code variables and functions are accessible, that is, from which parts of the program you can reach them. Scope comes from the structure of the code: every function and every block creates its own environment nested inside the outer one.

Theory

TL;DR

  • Global scope: declarations outside functions and blocks, reachable anywhere in the code.
  • Function scope: variables declared inside a function are reachable only inside it.
  • Block scope: let and const inside { } are reachable only within that block.
  • var has no block scope, it leaks up to the nearest function or to the global scope.
  • JavaScript uses lexical (static) scope: access is decided by where functions sit in the code, not by where they are called.
  • An inner function remembers the environment it was created in, and that is a closure.

Quick example

javascript
const appName = 'Notes'; // global scope function render() { const title = 'Hello'; // function scope if (title) { const suffix = '!'; // block scope console.log(title + suffix + ' ' + appName); // Hello! Notes } console.log(suffix); // ReferenceError: suffix is not defined } render(); console.log(title); // ReferenceError: title is not defined

Global scope

Variables declared outside functions or blocks are available everywhere in the code, including inside any function.

javascript
let name = 'Tim'; // global variable function greet() { console.log('Hello, ' + name); // available here } greet(); // Hello, Tim console.log(name); // available here too

Global variables are best avoided: they live for the whole run of the program and any module can overwrite them.

Function scope

Variables declared with var, let or const inside a function are available only inside that function.

javascript
function example() { let message = 'Inside function'; console.log(message); // works } example(); console.log(message); // error: message is not defined

Every call creates a fresh environment, so locals from different calls never interfere with each other.

Block scope

Variables declared with let or const inside a block { } (the body of if, for, while, or just a bare pair of braces) are available only within that block.

javascript
if (true) { const x = 10; let y = 20; var z = 30; // var has no block scope } console.log(z); // 30 (var is visible outside the block) console.log(x); // error: x is not defined console.log(y); // error: y is not defined

This is exactly why var behaves differently from let in a loop: var creates one variable for the whole function, while let creates a new one per iteration.

Lexical scope

JavaScript uses lexical (static) scope: access to variables is determined by where the functions are placed in the code, not by where they are called from.

javascript
function outer() { const outerVar = 'I am outside'; function inner() { console.log(outerVar); // has access to outerVar } return inner; } const fn = outer(); fn(); // "I am outside"

Here inner remembered the environment it was created in, and that is already a closure.

Variable lookup walks up the scope chain: the own scope first, then the outer one, and so on up to the global scope. If nothing is found, you get a ReferenceError.

Summary

Scope typeWhere it is createdAvailability
GlobalOutside functions and blocksEverywhere
FunctionInside a functionOnly inside that function
BlockInside { } (if, for, etc.)Only within the block
LexicalAt the time the code is writtenAccess to variables of outer scopes

Common mistakes

  • Assuming var is block scoped. It is not, so the variable leaks out of an if or for into the whole function.
  • Confusing lexical scope with dynamic scope: where a function is called from does not affect variable visibility at all.
  • Creating a variable without a declaration (count = 1) and accidentally getting a global one; in strict mode this is a ReferenceError.
  • Touching a let or const before its declaration line: the binding already exists but sits in the temporal dead zone, which throws a ReferenceError.
  • Relying on global variables to pass data between modules instead of parameters and return values.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.