JavaScript Fundamentals
How JavaScript Works
Execution Context
Everything in JavaScript runs inside an Execution Context, which consists of two main components:
- Memory Component (Variable Environment)
- Stores variables and function declarations as key-value pairs.
- Variables are initialized with
undefined
. - Functions are stored entirely.
- Code Component (Thread of Execution)
- Executes code line-by-line.
Key Characteristics of JavaScript
- Synchronous: Executes one statement at a time, in order.
- Single-threaded: Can process only one task at a time.
Phases of Code Execution
- Global Execution Context (GEC) Creation
- Automatically created when a JavaScript program starts.
- Includes both Memory and Code components.
- Memory Creation Phase
- Variables: allocated and set to
undefined
. - Functions: stored with full definitions.
- Variables: allocated and set to
- Code Execution Phase
- Code runs line-by-line using the memory set in the first phase.
- Function Invocation
- Each function call creates a new Local Execution Context.
- It goes through the same memory and execution phases.
- Context is pushed to and popped from the Call Stack.
Call Stack
- Manages the order of execution.
- The GEC is pushed first.
- Each function call pushes a new context.
- On return or end, contexts are popped.
- Finally, the GEC is removed.
Hoisting
- Memory Allocation Before Execution
- Variables: initialized to
undefined
. - Function declarations: hoisted with full body.
- Variables: initialized to
- Arrow Functions vs Regular Functions
- Arrow functions are treated as variables (initialized to
undefined
). - Regular function declarations are fully hoisted.
- Arrow functions are treated as variables (initialized to
- Hoisting Mechanism
- JS engine scans declarations before execution.
- Enables calling functions before their declaration (if using function declarations).
Global Environment
- Shortest JavaScript Program
- Even an empty file creates:
- A Global Execution Context
- A Global Object (
window
in browsers) - The global
this
(this === window
istrue
)
- Even an empty file creates:
- Global Scope Access
- Variables declared outside functions are accessible via
window
(e.g.,window.a
).
- Variables declared outside functions are accessible via
Understanding undefined
vs not defined
undefined
: Variable is declared but not initialized.not defined
: Variable was never declared.- JavaScript is weakly typed: variables don’t need explicit data types.
Scope and Lexical Environment
- Lexical Environment
- Created with every Execution Context.
- Contains local memory and a reference to its parent environment.
- Scope Chain
- Variable lookup follows the chain of lexical environments.
- If not found, the engine goes up recursively.
- If the variable isn’t found in any environment, it’s “not in scope.”
Hoisting and Variable Behavior in JavaScript
Hoisting of let
, const
, and var
let
andconst
are hoisted, but not initialized.- Accessing them before initialization results in a Temporal Dead Zone (TDZ) error.
var
is hoisted and initialized withundefined
, so no TDZ.
Memory Allocation Differences
- JavaScript stores
let
andconst
in a separate memory space from the Global Execution Context (GEC), causing the Temporal Dead Zone. var
is stored in the Global Execution Context.
Blocks and Scope in JavaScript
What is a Block?
- A block is code enclosed within curly braces
{}
. - Multiple statements are grouped into a block to be used where JavaScript expects a single statement—e.g., in
if
,else
, loops, and functions.
Block Scope and Memory
- Variables declared with
let
andconst
inside a block are stored in separate block-level memory, not in the global or function scope.- This is why
let
andconst
are called block-scoped.
- This is why
Variable Shadowing
- Shadowing occurs when a variable declared in an inner scope (e.g., inside a block) has the same name as one in an outer scope.
- Shadowing is allowed as long as the inner declaration doesn’t cross the boundary of the original scope.
- If it does, it can cause errors or unexpected behavior.
- Illegal Shadowing
- Shadowing a
let
orconst
variable with avar
declaration is illegal and throws an error due to differences in scope and hoisting behavior.
- Shadowing a
Scope Behavior of var
vs let
and const
- A
var
variable is function-scoped or globally scoped (if declared outside any function).- It is not restricted by block scope and can be accessed outside the block.
- In contrast,
let
andconst
are confined to the block in which they are declared.
Closures in JavaScript
Understanding Closures
- A closure is a function bundled with its lexical scope—i.e., it remembers the environment in which it was created.
- Even after a function is returned from another function, it retains access to its original lexical environment and local variables.
- This allows the function to access and manipulate variables from its parent scope even after that parent function has finished execution.
Function Behavior in Closures
- Writing
return function x() { ... }
or simplyreturn function() { ... }
means you are returning a function reference, not its result.- The function is not executed immediately, but can be executed later.
- The returned function maintains a reference to the variables in its closure.
- So, any modification to those variables inside the returned function will be reflected across calls, as they are not re-initialized.
1. How setTimeout
Works
- When
setTimeout
is called, the callback function is stored separately (typically in a Web API environment). - A timer is attached, and once it expires, the function is moved back into the callback queue.
- When the call stack is empty, the callback function is pushed onto the call stack and executed.
2. var
and Closure Behavior
- If you use
var
inside a loop withsetTimeout
, it doesn’t create a new scope for each iteration. - Since
var
is function-scoped and holds a reference, by the time the timeout function executes, the loop has already completed, and it shows the final value of the variable.
3. Using let
or const
Instead
let
andconst
are block-scoped, so a new copy of the variable is created in each iteration.- This allows
setTimeout
to access the correct value per iteration, even without needing closures.
📘 JavaScript Function Types & First-Class Functions — Quick Reference
Type | Description | Hoisting | Example |
---|---|---|---|
Function Declaration | Regular named function using function keyword | ✅ Yes | function greet() {} |
Function Expression | Function assigned to a variable | ❌ No | const greet = function() {} |
Anonymous Function | Function without a name (often used in expressions/callbacks) | ❌ No | const greet = function() {} |
Named Function Expression | Function with internal name, assigned to a variable | ❌ No | const greet = function welcome() {} welcome() ❌ Not accessible outside |
🧠 First-Class Functions in JavaScript
Capability | Description | Example |
---|---|---|
✅ Assign to variables | Functions as values | const fn = function() {} |
✅ Pass as arguments | Functions as parameters | setTimeout(() => {}, 1000) |
✅ Return from other functions | Functions as return values | return function() {} |
✅ Used in closures | Functions inside other functions with scope | function outer() { return function() {} } |
🧠 CallBack Functions
- Callback: Function passed as an argument to another function.
- First-class functions → allow passing functions around.
- Executed later by the receiving function.
- Enable async operations in JS (single-threaded).
- Prevent blocking main thread.
- Basis for Promises & async/await.
Examples:
function x(y) { console.log("x"); y(); }
x(function y() { console.log("y"); });
setTimeout(function() { console.log("Hi"); }, 5000);