Functions become even more powerful when combined with concepts like scope, closures, and the call stack.
These concepts are used extensively in modern JavaScript frameworks such as:
Understanding these topics is essential before learning advanced JavaScript and React.
Scope determines where variables can be accessed.
Think of scope as the visibility area of a variable.
Inside Scope → Accessible
Outside Scope → Not Accessible
JavaScript has three main types of scope:
Variables declared outside of any function belong to the global scope.
They can be accessed anywhere in the program.
const name = "Samir";
function greet() {
console.log(name);
}
greet();
Output
Samir
Global Scope
│
├── name
├── greet()
└── other functions
Every function can access global variables.
Variables declared inside a function exist only inside that function.
function greet() {
const message = "Hello";
console.log(message);
}
greet();
Output
Hello
Outside the function
console.log(message);
Output
ReferenceError
greet()
│
└── message
Variables declared using let or const are block scoped.
if (true) {
const age = 21;
}
console.log(age);
Output
ReferenceError
{
age
}
The variable exists only inside the block.
When JavaScript looks for a variable, it searches from the innermost scope outward.
const country = "Nepal";
function outer() {
function inner() {
console.log(country);
}
inner();
}
outer();
Output
Nepal
Current Scope
↓
Parent Scope
↓
Global Scope
This process is called the Scope Chain.
Lexical means:
Determined By Position In Code
A function can access variables from the place where it was defined, not where it is called.
const name = "Samir";
function greet() {
console.log(name);
}
greet();
Output
Samir
Why?
Because greet() was created inside the scope where name exists.
function outer() {
const message = "Hello";
function inner() {
console.log(message);
}
inner();
}
outer();
Output
Hello
Global Scope
│
└── outer()
│
└── message
│
└── inner()
inner() can access message because of lexical scope.
A Closure occurs when a function remembers variables from its lexical scope even after the outer function has finished executing.
Closures are one of the most important concepts in JavaScript.
function outer() {
const name = "Samir";
function inner() {
console.log(name);
}
return inner;
}
const fn = outer();
fn();
Output
Samir
Even though outer() has already finished executing, the returned function still remembers the variable name.
This memory is called a Closure.
outer()
│
├── name = "Samir"
│
└── returns inner()
After outer() finishes
│
└── inner() still remembers name
function counter() {
let count = 0;
return function() {
count++;
console.log(count);
};
}
const increment = counter();
increment();
increment();
increment();
Output
1
2
3
The inner function remembers the count variable through a closure.
function createGreeting(name) {
return function() {
console.log(
`Hello ${name}`
);
};
}
const greetSamir =
createGreeting("Samir");
greetSamir();
Output
Hello Samir
Closures are heavily used in:
Almost every modern JavaScript application uses closures.
JavaScript uses a Call Stack to keep track of function execution.
It follows the Last In, First Out (LIFO) principle.
Last In
↓
First Out
function one() {
two();
}
function two() {
three();
}
function three() {
console.log("Done");
}
one();
Start
↓
one()
↓
two()
↓
three()
↓
console.log()
↓
Complete
↓
three() removed
↓
two() removed
↓
one() removed
┌──────────────┐
│ console.log │
├──────────────┤
│ three() │
├──────────────┤
│ two() │
├──────────────┤
│ one() │
└──────────────┘
The last function added is the first one removed.
If recursive functions never stop, the call stack keeps growing.
function test() {
test();
}
test();
Output
RangeError:
Maximum call stack size exceeded
Every recursive function must have a stopping condition.
JavaScript includes many built-in functions.
These are available without creating them yourself.
parseInt("100");
Output
100
parseFloat("99.99");
Output
99.99
isNaN("Hello");
Output
true
Number("100");
Output
100
String(123);
Output
"123"
const text = "hello";
console.log(
text.toUpperCase()
);
Output
HELLO
JavaScript provides the built-in Math object.
Math.random();
Output
0.34872
(Random value between 0 and 1)
Math.round(4.6);
Output
5
Math.floor(4.9);
Output
4
Math.max(
10,
20,
30
);
Output
30
new Date();
Returns the current date and time.
new Date().getFullYear();
Example Output
2026
console.log("Hello");
console.error("Error");
console.table([
"Apple",
"Mango"
]);
Displays data in a table format inside the browser console.
Runs a function once after a delay.
setTimeout(() => {
console.log("Hello");
}, 2000);
Output after:
2 Seconds
Runs a function repeatedly.
setInterval(() => {
console.log("Running");
}, 1000);
Output
Every Second
| Function | Purpose |
|---|---|
parseInt() |
Convert String → Integer |
parseFloat() |
Convert String → Decimal |
Number() |
Convert to Number |
String() |
Convert to String |
Boolean() |
Convert to Boolean |
isNaN() |
Check if value is NaN |
setTimeout() |
Execute once after delay |
setInterval() |
Execute repeatedly |
| Scope | Closure |
|---|---|
| Determines variable visibility | Remembers variables |
| Exists while executing | Exists after outer function finishes |
| Controls access | Preserves data |
| Temporary | Persistent |
function createCounter() {
let count = 0;
return () => {
count++;
return count;
};
}
const counter =
createCounter();
console.log(counter());
console.log(counter());
console.log(counter());
Output
1
2
3
Concepts used
Function
↓
Lexical Scope
↓
Closure
↓
Call Stack
| Concept | Purpose |
|---|---|
| Scope | Variable visibility |
| Global Scope | Accessible everywhere |
| Function Scope | Accessible inside functions |
| Block Scope | Accessible inside blocks |
| Lexical Scope | Variables found based on code location |
| Closure | Function remembers variables |
| Call Stack | Tracks function execution |
| Built-in Functions | Ready-made JavaScript functions |
const and letAvoid using var in modern JavaScript.
const name = "Samir";
let count = 0;
Declare variables only where they are needed.
function calculate() {
const total = 100;
}
Closures are powerful but can keep variables in memory.
Only retain data that is actually needed.
if (n === 0) {
return;
}
Without a base case, recursion causes a stack overflow.
const timer = setInterval(() => {
console.log("Running");
}, 1000);
clearInterval(timer);
This helps prevent memory leaks.
Advanced functions are built on three fundamental ideas:
Scope
↓
Where Variables Can Be Accessed
Lexical Scope
↓
How Functions Find Variables
Closures
↓
How Functions Remember Variables
JavaScript executes every function using the Call Stack.
Call Stack
↓
Function Execution Order
These concepts are the foundation of React Hooks, event handlers, callbacks, timers, state management, and modern frontend development. Mastering them will make it much easier to understand advanced JavaScript and frameworks like React and Next.js.