Understanding Scope in JavaScript
One of the most important concepts every JavaScript developer should understand is scope.
Many strange bugs in JavaScript happen because developers do not fully understand where variables can be accessed and where they cannot.
Think of scope as the visibility area of a variable.
A variable can only be used inside the area where it is visible.
Imagine an office building.
Some documents are available only inside a specific department.
Some documents are available to the entire company.
Variables work in a very similar way.
JavaScript mainly provides:
Global Scope
Function Scope
Block Scope
Let's understand each one.
Global Scope
A variable declared outside any function or block is considered globally accessible.
Example:
var company = "WhosGeek";
console.log(company);
function showCompany() {
console.log(company);
}
showCompany();
Output:
WhosGeek
WhosGeek
Here the variable:
company
can be accessed from anywhere in the script.
Real World Example
Imagine a company notice board.
Every employee can read information placed on that board.
Global variables behave similarly.
Every function can access them.
Function Scope
Variables declared using var inside a function are only accessible within that function.
Example:
function test() {
var score = 100;
console.log(score);
}
test();
console.log(score);
Output:
100
ReferenceError
Why?
Because score only exists inside the function.
Once the function finishes execution, the variable is no longer accessible outside.
Block Scope
ES6 introduced block-scoped variables using:
let
const
A block means anything inside:
{
}
Example:
{
let age = 25;
const city = "Delhi";
}
console.log(age);
console.log(city);
Output:
ReferenceError
ReferenceError
Both variables are only accessible inside their block.
var vs let vs const
This is one of the most common JavaScript interview topics.
Many beginners use them interchangeably.
However, they behave differently.
var
Properties:
Function Scoped
Can be reassigned
Can be redeclared
Hoisted with undefined
Example:
var user = "Alex";
var user = "John";
console.log(user);
Output:
John
JavaScript allows redeclaration with var.
let
Properties:
Block Scoped
Can be reassigned
Cannot be redeclared
Hoisted but remains in Temporal Dead Zone
Example:
let age = 20;
age = 25;
console.log(age);
Output:
25
const
Properties:
Block Scoped
Cannot be reassigned
Cannot be redeclared
Example:
const PI = 3.14;
PI = 5;
Output:
TypeError
Because constants cannot be reassigned.
A Common Interview Question
What will be the output?
console.log(a);
var a = 10;
Output:
undefined
Why?
JavaScript internally treats it like:
var a;
console.log(a);
a = 10;
This behavior is called:
Hoisting
Hoisting Explained in Simple Words
Imagine a classroom.
Before students enter, the teacher prepares a list of student names.
The names exist before attendance starts.
Similarly, during the creation phase, JavaScript already knows which variables and functions exist.
This process is called hoisting.
Hoisting with var
Example:
console.log(name);
var name = "Devin";
Output:
undefined
The variable exists in memory but has not received a value yet.
Hoisting with let
Example:
console.log(age);
let age = 22;
Output:
ReferenceError
This happens because of the Temporal Dead Zone.
Temporal Dead Zone (TDZ)
This sounds complicated, but the idea is simple.
The Temporal Dead Zone is the time between:
Variable creation
and
Variable initialization
During this period JavaScript knows the variable exists but does not allow access to it.
Example:
console.log(user);
let user = "WhosGeek";
Output:
ReferenceError
Why Did JavaScript Introduce let and const?
Older JavaScript applications relied heavily on var.
This often caused bugs because variables leaked outside blocks.
Example:
if(true){
var username = "Alex";
}
console.log(username);
Output:
Alex
Even though it was declared inside an if block.
This caused confusion in large applications.
ES6 introduced:
let
const
to solve this problem.
Interactivity in JavaScript
When people say JavaScript makes websites interactive, what does that actually mean?
Imagine a website built only with HTML and CSS.
The page can display content.
But users cannot really interact with it.
JavaScript changes that.
It allows websites to react to user actions.
Examples:
Clicking buttons
Opening menus
Submitting forms
Showing notifications
Playing animations
Creating games
Without JavaScript, modern websites like:
Facebook
YouTube
Netflix
Amazon
would feel static.
Real World Example
Suppose a user clicks:
<button>Show Details</button>
JavaScript can respond:
button.addEventListener("click", () => {
details.style.display = "block";
});
Now the page reacts to user actions.
This is interactivity.
Undefined vs Null
This topic confuses almost every beginner.
Both seem similar.
But they represent different situations.
What is Undefined?
Undefined means:
A variable exists, but no value has been assigned yet.
Example:
let user;
console.log(user);
Output:
undefined
The variable was declared.
No value was assigned.
What is Null?
Null means:
The developer intentionally assigned an empty value.
Example:
let user = null;
console.log(user);
Output:
null
Here the developer is explicitly saying:
This variable currently has no value.
Easy Analogy
Imagine a parking lot.
Undefined:
A parking slot exists,
but nobody assigned a vehicle.
Null:
The parking slot was intentionally marked empty.
Both are empty.
But for different reasons.
Interview Question
console.log(undefined == null);
console.log(undefined === null);
Output:
true
false
Why?
Because:
==
performs type conversion.
Whereas:
===
checks both value and type.
Undeclared vs Undefined Variables
These are different concepts.
Undefined Variable
Declared but no value assigned.
let name;
console.log(name);
Output:
undefined
Undeclared Variable
Never declared at all.
console.log(username);
Output:
ReferenceError
JavaScript cannot find the variable.
Understanding Functions in JavaScript
If variables are the containers of JavaScript, then functions are the workers.
A function is simply a reusable block of code that performs a specific task.
Instead of writing the same code again and again, we place it inside a function and call it whenever we need it.
Imagine working in a restaurant.
Instead of teaching every employee how to cook every dish from scratch, the restaurant creates a standard process.
Whenever someone orders a pizza, the same process is followed.
Functions work in a very similar way.
We define a task once and reuse it multiple times.
Why Do Functions Exist?
Without functions:
let num1 = 10;
let num2 = 20;
console.log(num1 + num2);
let num3 = 30;
let num4 = 40;
console.log(num3 + num4);
We keep repeating logic.
With functions:
function add(a, b){
return a + b;
}
console.log(add(10,20));
console.log(add(30,40));
Now the code becomes:
Cleaner
Reusable
Easier to maintain
Types of Functions in JavaScript
JavaScript provides several ways to create functions.
The most common ones are:
Function Declaration
Function Expression
Anonymous Function
Arrow Function
Immediately Invoked Function Expression (IIFE)
Generator Function
Let's understand each one.
Function Declaration
A function declaration is the most common way of creating functions.
Example:
function addNumbers(a,b){
return a + b;
}
console.log(addNumbers(5,10));
Output:
15
Why Are Function Declarations Popular?
Because they are easy to read.
When another developer opens your code, they immediately understand:
function calculateTax(){}
function sendEmail(){}
function createUser(){}
The names explain the purpose.
Function Declarations Are Hoisted
One interesting feature is:
hello();
function hello(){
console.log("Hello World");
}
Output:
Hello World
The function works even before its declaration appears.
Why?
Because function declarations are hoisted during JavaScript's creation phase.
Function Expressions
A function expression stores a function inside a variable.
Example:
const multiply = function(a,b){
return a * b;
};
console.log(multiply(2,5));
Output:
10
Difference Between Function Declaration and Function Expression
Function Declaration:
function test(){
}
Function Expression:
const test = function(){
}
The major difference is hoisting.
Interview Question
What happens?
hello();
const hello = function(){
console.log("Hi");
}
Output:
ReferenceError
Because function expressions are not fully hoisted like function declarations.
Anonymous Functions
Anonymous means:
Without a name
Example:
function(){
console.log("Hello");
}
Notice:
No function name exists.
Anonymous functions are commonly used:
Inside callbacks
Event handlers
Array methods
Timers
Real World Example
Suppose a user clicks a button.
button.addEventListener("click", function(){
console.log("Button Clicked");
});
The function only needs to run when the button is clicked.
No need to give it a separate name.
This is why anonymous functions are very common in JavaScript applications.
Immediately Invoked Function Expression (IIFE)
One of the most interesting JavaScript patterns is the IIFE.
Pronounced:
Iffy
An IIFE runs immediately after being created.
Example:
(function(){
console.log("Executed Immediately");
})();
Output:
Executed Immediately
Why Were IIFEs Popular?
Before:
let
const
developers used IIFEs to create private scope.
Example:
(function(){
var secret = "hidden";
console.log(secret);
})();
Outside:
console.log(secret);
Output:
ReferenceError
The variable remains private.
Real World Analogy
Imagine writing notes inside a locked diary.
The notes are available inside the diary.
Nobody outside can access them.
That is how IIFE scope works.
Arrow Functions
Arrow functions were introduced in ES6.
They provide shorter syntax.
Traditional function:
function add(a,b){
return a+b;
}
Arrow version:
const add = (a,b) => {
return a+b;
}
Even shorter:
const add = (a,b) => a+b;
Why Developers Love Arrow Functions
Benefits:
Short syntax
Cleaner code
Easy callbacks
Common in React and Node.js
Example:
const users = [1,2,3];
users.map(num => num * 2);
Much cleaner than:
users.map(function(num){
return num * 2;
});
Arrow Function vs Regular Function
This is an extremely common interview topic.
Consider:
const person = {
name:"Alex",
greet:function(){
console.log(this.name);
}
};
person.greet();
Output:
Alex
Now:
const person = {
name:"Alex",
greet:() => {
console.log(this.name);
}
};
person.greet();
Output:
undefined
Why?
Arrow functions do not create their own:
this
Instead they borrow:
this
from their surrounding scope.
This is one of the biggest differences between regular functions and arrow functions.
What Are Closures in JavaScript?
Closures are one of the most important concepts in JavaScript.
Unfortunately, they are also one of the most misunderstood.
A closure occurs when:
An inner function remembers variables from its outer function even after the outer function has finished execution.
Sounds complicated.
Let's simplify it.
Real World Analogy
Imagine leaving your office for home.
Before leaving, you put some important notes into your notebook.
Even after leaving the office, you still have access to those notes.
Closures behave similarly.
The outer function finishes execution.
But the inner function still remembers variables from that scope.
Simple Closure Example
function outer(){
let message = "Hello Developer";
function inner(){
console.log(message);
}
return inner;
}
const result = outer();
result();
Output:
Hello Developer
What Happened Here?
When:
outer()
finished execution, many beginners assume:
message
should disappear.
However:
inner()
still remembers it.
This remembered environment is called a Closure.
Practical Use Case of Closures
Closures are heavily used for:
Data privacy
Counters
Authentication logic
Caching
Event handlers
React hooks
Counter Example
function createCounter(){
let count = 0;
return function(){
return count++;
}
}
const counter = createCounter();
console.log(counter());
console.log(counter());
console.log(counter());
Output:
0
1
2
Why Is This Powerful?
Because:
count
cannot be directly modified from outside.
Yet it remembers its value.
This is a perfect example of private state management.
Scope Chain Explained
When JavaScript tries to find a variable, it follows a chain.
Example:
let company = "WhosGeek";
function outer(){
let department = "Engineering";
function inner(){
console.log(company);
console.log(department);
}
inner();
}
outer();
Output:
WhosGeek
Engineering
How JavaScript Searches
JavaScript checks:
Current Scope
Parent Scope
Global Scope
This process is called:
Scope Chain
Understanding String Methods in JavaScript
Strings are one of the most commonly used data types in JavaScript.
Whenever we work with:
User names
Emails
Passwords
Search inputs
URLs
Messages
we are working with strings.
JavaScript provides many built-in methods that make string manipulation easier.
Think of string methods as tools in a toolbox.
Instead of building everything from scratch, JavaScript already gives us ready-made tools.
The trim() Method
One of the most useful string methods is:
trim()
Its job is simple:
Remove extra spaces from the beginning and end of a string.
Example:
let str = " hello world ";
console.log(str.length);
Output:
17
Now:
let cleaned = str.trim();
console.log(cleaned.length);
Output:
11
Real World Example
Imagine a user enters:
alex@gmail.com
with accidental spaces.
Without trim():
" alex@gmail.com"
The login might fail.
Using trim():
email = email.trim();
removes unnecessary spaces.
This is why trim() is heavily used in forms.
The slice() Method
The slice() method extracts part of a string.
Example:
let text = "JavaScript";
console.log(text.slice(0,4));
Output:
Java
Understanding the Index
J a v a S c r i p t
0 1 2 3 4 5 6 7 8 9
When we write:
text.slice(0,4)
JavaScript starts from:
0
and stops before:
4
Result:
Java
Negative Indexes in slice()
One advantage of slice() is support for negative indexes.
Example:
let text = "JavaScript";
console.log(text.slice(-6));
Output:
Script
This starts counting from the end.
Interview Question
What is the difference between:
slice()
and
substring()
The biggest answer:
slice()
supports negative indexes.
substring()
does not.
The substring() Method
substring() also extracts part of a string.
Example:
let text = "JavaScript";
console.log(text.substring(0,4));
Output:
Java
Interesting Behavior
Example:
console.log("Hello".substring(3,1));
Output:
el
Why?
Because substring automatically swaps the values.
Internally:
substring(1,3)
Negative Values
Example:
console.log("Hello".substring(-2,3));
Output:
Hel
substring treats negative values as:
0
This behavior often appears in interviews.
charAt()
Used to access a character at a specific position.
Example:
let word = "JavaScript";
console.log(word.charAt(4));
Output:
S
indexOf()
Used to find the position of a character or word.
Example:
let text = "Hello World";
console.log(text.indexOf("W"));
Output:
6
Real World Example
Search functionality often uses:
indexOf()
to determine whether text exists inside another string.
Array Methods in JavaScript
Arrays are everywhere.
Examples:
let users = [];
let products = [];
let orders = [];
Most backend APIs return arrays.
Most frontend applications display arrays.
Because of this, array methods are extremely important.
push()
Adds an item to the end of an array.
Example:
let arr = [1,2,3];
arr.push(4);
console.log(arr);
Output:
[1,2,3,4]
pop()
Removes the last element.
Example:
let arr = [1,2,3];
arr.pop();
console.log(arr);
Output:
[1,2]
shift()
Removes the first element.
Example:
let arr = [1,2,3];
arr.shift();
console.log(arr);
Output:
[2,3]
unshift()
Adds an item to the beginning.
Example:
let arr = [2,3];
arr.unshift(1);
console.log(arr);
Output:
[1,2,3]
splice()
One of the most powerful array methods.
Used to:
Add elements
Remove elements
Replace elements
Example:
let arr = [1,2,3,4];
arr.splice(1,2,"new");
console.log(arr);
Output:
[1,"new",4]
Why Developers Love splice()
Suppose we have:
Cart Products
and want to remove an item.
splice() makes that easy.
Difference Between slice() and splice()
This interview question appears frequently.
slice()
Does NOT modify original array
splice()
Modifies original array
Example:
let arr = [1,2,3,4];
let result = arr.slice(1,3);
Output:
result → [2,3]
arr → [1,2,3,4]
Original array remains unchanged.
Higher Order Functions
One of JavaScript's superpowers is:
Higher Order Functions
A Higher Order Function is a function that:
Accepts another function as an argument
Returns another function
Examples:
map()
filter()
reduce()
find()
forEach()
These methods are used daily in modern JavaScript applications.
map()
The map() method transforms every element of an array.
Example:
let numbers = [1,2,3];
let doubled = numbers.map(num => num * 2);
console.log(doubled);
Output:
[2,4,6]
Real World Example
Suppose we receive products from an API.
products.map(product => ({
...product,
price: product.price * 1.18
}))
We can update all product prices at once.
filter()
Used to return elements matching a condition.
Example:
let numbers = [1,2,3,4,5,6];
let even = numbers.filter(num => num % 2 === 0);
console.log(even);
Output:
[2,4,6]
Real World Example
Filter active users:
users.filter(user => user.active);
Filter completed orders:
orders.filter(order => order.status === "completed");
find()
Returns the first matching element.
Example:
let numbers = [5,12,8,130];
let result = numbers.find(num => num > 10);
console.log(result);
Output:
12
Difference Between find() and filter()
find():
Returns one element
filter():
Returns array
findIndex()
Returns index of first matching element.
Example:
let arr = [1,2,3,4];
let index = arr.findIndex(num => num > 2);
console.log(index);
Output:
2
forEach()
Used when we simply want to loop.
Example:
let users = ["Alex","John","David"];
users.forEach(user => {
console.log(user);
});
Output:
Alex
John
David
Important Interview Point
forEach() returns:
undefined
Many beginners expect a new array.
It does not create one.
reduce()
One of the most powerful array methods.
reduce() converts an entire array into a single value.
Example:
let numbers = [3,4,5,6];
let total = numbers.reduce((acc,curr)=>{
return acc + curr;
},0);
console.log(total);
Output:
18
Understanding acc and curr
acc
means:
Accumulator
Stores the running result.
curr
means:
Current Element
Real World Example
Calculate cart total:
cart.reduce((total,item)=>{
return total + item.price;
},0)
This is extremely common in e-commerce projects.
Understanding NaN in JavaScript
One of the most confusing values in JavaScript is:
NaN
which stands for:
Not a Number
However, the strange part is:
console.log(typeof NaN);
Output:
number
Most beginners see this and think:
"How can Not a Number be a number?"
Let's understand why.
What Exactly Is NaN?
NaN is a special value that represents an invalid mathematical result.
Example:
console.log(Number("hello"));
Output:
NaN
JavaScript tried to convert:
"hello"
into a number.
It failed.
So it returned:
NaN
Real World Analogy
Imagine a calculator.
You type:
apple ÷ banana
The calculator has no idea how to perform that operation.
Instead of crashing, it displays:
Invalid Result
JavaScript's version of that invalid result is:
NaN
A Popular Interview Question
What will be the output?
console.log(NaN === NaN);
Output:
false
Why?
According to JavaScript rules:
NaN
is not equal to anything.
Not even itself.
This is one of JavaScript's famous interview questions.
Correct Way to Check NaN
Instead of:
value === NaN
Use:
Number.isNaN(value);
Example:
console.log(Number.isNaN(NaN));
Output:
true
What Is Type Coercion?
JavaScript is a dynamically typed language.
This means JavaScript automatically converts values from one type to another when needed.
This automatic conversion is called:
Type Coercion
Example 1
console.log("5" + 2);
Output:
52
Why?
JavaScript converts:
2
into:
"2"
Then:
"5" + "2"
becomes:
"52"
Example 2
console.log("5" - 2);
Output:
3
Why?
The subtraction operator only works with numbers.
JavaScript converts:
"5"
into:
5
Then:
5 - 2
becomes:
3
Common Type Coercion Examples
Boolean to Number
console.log(true + 1);
Output:
2
Because:
true = 1
False to Number
console.log(false + 5);
Output:
5
Because:
false = 0
Empty String
console.log("" + 5);
Output:
"5"
String concatenation occurs.
Difference Between == and ===
This is one of the most frequently asked JavaScript interview questions.
Double Equals
==
Performs:
Type Conversion
Example:
console.log(5 == "5");
Output:
true
Because JavaScript converts:
"5"
into:
5
before comparison.
Triple Equals
===
Performs:
Strict Comparison
Example:
console.log(5 === "5");
Output:
false
Because:
Number !== String
Interview Rule
Whenever possible:
Use:
===
instead of:
==
because it avoids unexpected coercion.
What Is Strict Mode?
Strict Mode was introduced in ES5.
It helps developers write safer JavaScript.
Enable it like this:
"use strict";
Why Was Strict Mode Introduced?
Before strict mode:
name = "Alex";
console.log(name);
This works.
JavaScript automatically creates a global variable.
This can create difficult bugs in large applications.
With Strict Mode
"use strict";
name = "Alex";
Output:
ReferenceError
JavaScript now forces us to declare variables properly.
Benefits of Strict Mode
Prevents accidental global variables
Prevents duplicate parameter names
Makes debugging easier
Helps write cleaner code
Understanding Map in JavaScript
Before ES6, developers mainly used objects.
Example:
let user = {
name: "Alex"
};
ES6 introduced:
Map
which stores key-value pairs more efficiently.
Creating a Map
const person = new Map();
Adding Values
person.set("name", "Alex");
person.set("age", 25);
Reading Values
console.log(
person.get("name")
);
Output:
Alex
Checking Key Existence
console.log(
person.has("name")
);
Output:
true
Why Use Map Instead of Object?
Map provides:
Better performance
Any data type as keys
Preserves insertion order
Built-in utility methods
Example
const map = new Map();
map.set(1, "One");
map.set(true, "Boolean");
map.set({}, "Object");
Objects cannot handle this as elegantly.
Understanding Set
A Set stores:
Unique Values Only
Example
const set = new Set([
1,
2,
3,
3,
4,
4
]);
console.log(set);
Output:
Set(4) {1,2,3,4}
Duplicates are automatically removed.
Real World Example
Suppose we have:
let emails = [
"alex@gmail.com",
"alex@gmail.com",
"john@gmail.com"
];
We can remove duplicates:
let uniqueEmails =
[...new Set(emails)];
Result:
[
"alex@gmail.com",
"john@gmail.com"
]
Map vs Set
| Feature | Map | Set |
|---|---|---|
| Key-Value Pairs | ✅ | ❌ |
| Unique Values | ❌ | ✅ |
| Maintains Order | ✅ | ✅ |
| Duplicate Values | ❌ | ❌ |
Understanding WeakMap
A WeakMap is similar to Map.
However:
Keys Must Be Objects
Example:
let user = {
name:"Alex"
};
let weakMap = new WeakMap();
weakMap.set(
user,
"Secret Data"
);
Why Does WeakMap Exist?
The biggest reason:
Memory Management
When an object is no longer used:
JavaScript can automatically remove it from memory.
This helps prevent:
Memory Leaks
Real World Analogy
Imagine a visitor pass system.
When visitors leave the building, their temporary passes are automatically destroyed.
WeakMap behaves similarly.
Unused entries disappear automatically.
Understanding WeakSet
WeakSet is similar to Set.
However:
Stores objects only
Objects are weakly referenced
Not iterable
Example:
let user = {
name:"Alex"
};
let weakSet =
new WeakSet();
weakSet.add(user);
Why Use WeakSet?
Useful for:
Tracking objects
Temporary caching
Memory-sensitive applications
Interview Question
Can we store numbers inside WeakSet?
Example:
weakSet.add(10);
Output:
TypeError
Because:
WeakSet
only stores objects.
Memory Leak Problem
Suppose an application creates:
10000
objects.
If references remain forever:
Memory usage keeps growing.
WeakMap and WeakSet solve this problem by allowing garbage collection.
This makes them valuable for large-scale applications.
Interview Takeaway
NaN
typeof NaN
returns:
number
Type Coercion
JavaScript automatically converts data types.
Equality Operators
==
allows coercion.
===
does not.
Strict Mode
Helps write safer code.
Map
Stores key-value pairs.
Set
Stores unique values.
WeakMap
Object keys only.
Garbage collection friendly.
WeakSet
Stores object references only.
Great for memory optimization.
These concepts appear repeatedly in JavaScript interviews, React applications, Node.js projects, and large-scale enterprise systems.
Functional Programming in JavaScript
When most beginners start learning JavaScript, they focus on variables, loops, and functions.
As they grow, they discover another programming style called:
Functional Programming (FP)
Functional Programming is a way of writing code where functions become the main building blocks of an application.
Instead of constantly modifying data, we focus on creating small reusable functions.
Simple Definition
Functional Programming is a programming style where:
Functions are treated like values
Functions can be passed around
Functions can return other functions
Functions avoid side effects
Functions produce predictable outputs
Real World Example
Imagine a factory.
Traditional programming might involve one giant machine doing everything.
Functional Programming is like having:
One machine for cutting
One machine for painting
One machine for packaging
Each machine performs one specific task.
This makes the system easier to maintain.
What Are Pure Functions?
One of the most important ideas in Functional Programming is:
Pure Functions
A pure function:
Always returns the same output for the same input
Does not modify external data
Example:
function add(a,b){
return a + b;
}
Input:
add(2,3)
Output:
5
Every time.
No surprises.
Impure Function Example
let total = 0;
function add(value){
total += value;
return total;
}
This function depends on external data.
Results may change.
Therefore it is considered impure.
First-Class Functions
One of JavaScript's superpowers is:
Functions Are First-Class Citizens
This means functions can:
Be stored in variables
Be passed as arguments
Be returned from functions
Example:
const greet = function(){
console.log("Hello");
};
The function is stored inside a variable.
Passing Functions as Arguments
function welcome(name){
return `Hello ${name}`;
}
function processUser(name, callback){
return callback(name);
}
console.log(
processUser(
"Alex",
welcome
)
);
Output:
Hello Alex
Why Is This Useful?
Because it allows flexible and reusable code.
This idea powers:
React
Node.js
Express
Array Methods
Event Handlers
Higher Order Functions Deep Dive
A Higher Order Function (HOF) is a function that:
Accepts another function
Returns another function
Example:
map()
filter()
reduce()
find()
All are Higher Order Functions.
Why Are Higher Order Functions Important?
Without HOFs:
for(let i=0;i<arr.length;i++){
}
We repeatedly write loops.
With HOFs:
arr.map()
arr.filter()
arr.reduce()
The logic becomes cleaner and easier to read.
What Is Currying?
Currying is one of those concepts that sounds complicated but is actually simple.
Normally:
function add(a,b,c){
return a+b+c;
}
Usage:
add(1,2,3);
Curried Version
function curryAdd(a){
return function(b){
return function(c){
return a+b+c;
}
}
}
Usage:
curryAdd(1)(2)(3);
Output:
6
Real World Analogy
Imagine ordering food.
Instead of placing the entire order at once:
Pizza
Drink
Dessert
You place it step by step.
JavaScript waits until all required information is available before producing the final result.
Currying works similarly.
Why Use Currying?
Benefits:
Function Reusability
Cleaner Code
Partial Application
Functional Programming Patterns
Example:
const add10 = curryAdd(10);
Now:
add10(5)(2);
becomes:
17
Constructor Functions
Before ES6 Classes existed, developers used Constructor Functions.
A Constructor Function is used to create multiple similar objects.
Example:
function Person(name, age){
this.name = name;
this.age = age;
}
Creating objects:
const user1 =
new Person("Alex",25);
const user2 =
new Person("John",30);
Output:
{
name:"Alex",
age:25
}
Why Use Constructor Functions?
Imagine building:
1000 Users
Instead of writing:
let user1 = {};
let user2 = {};
let user3 = {};
We create a blueprint.
The constructor creates objects from that blueprint.
What Is a Prototype?
One of JavaScript's most important concepts is:
Prototype
JavaScript uses:
Prototypal Inheritance
rather than traditional class inheritance.
Every object has access to a prototype.
Example
function Person(name){
this.name = name;
}
Person.prototype.sayHello =
function(){
return `Hello ${this.name}`;
};
Now:
const user =
new Person("Alex");
console.log(
user.sayHello()
);
Output:
Hello Alex
Why Use Prototype?
Without prototype:
Every object would create its own copy of methods.
With prototype:
Methods are shared.
This saves memory.
Real World Analogy
Imagine a school.
Every student has access to the same rule book.
Instead of giving each student a separate copy, they share one master copy.
That shared copy is similar to a prototype.
Classes in JavaScript
ES6 introduced:
class
Classes make object creation easier and cleaner.
Example:
class Person{
constructor(name){
this.name = name;
}
greet(){
return `Hello ${this.name}`;
}
}
Creating objects:
const user =
new Person("Alex");
Why Classes Were Introduced
Before classes:
Constructor Functions
+
Prototype
were required.
Classes provide a cleaner syntax.
Internally JavaScript still uses prototypes.
Classes are essentially:
Syntactic Sugar
over prototypes.
Object-Oriented Programming (OOP)
Object-Oriented Programming is a way of organizing software using:
Objects
rather than only functions.
Why OOP Exists
Imagine building:
E-commerce
Banking Application
Social Media App
Thousands of entities exist.
Examples:
User
Product
Order
Payment
Review
OOP helps organize these entities.
The Four Pillars of OOP
The most common interview question:
What are the pillars of OOP?
Answer:
Encapsulation
Abstraction
Inheritance
Polymorphism
Let's understand each one.
Encapsulation
Encapsulation means:
Combining Data and Methods
into one unit.
Example:
class Person{
constructor(name){
this.name = name;
}
getName(){
return this.name;
}
}
Data and behavior stay together.
Real World Example
A medicine capsule contains different ingredients wrapped together.
Similarly:
Data + Functions
are wrapped inside a class.
Abstraction
Abstraction means:
Hide complexity.
Show only necessary details.
Example:
class Car{
start(){
this.injectFuel();
this.ignite();
}
}
User only calls:
car.start();
They don't need to know the internal engine process.
Real World Example
When driving a car:
You press:
Start Button
You don't need to understand:
Fuel Injection
Engine Combustion
Spark Timing
This is abstraction.
Inheritance
Inheritance allows one class to use properties and methods of another class.
Example:
class Animal{
eat(){
console.log("Eating");
}
}
Child class:
class Dog extends Animal{
}
Now:
const dog =
new Dog();
dog.eat();
Output:
Eating
Why Use Inheritance?
Avoid code duplication.
Instead of rewriting common functionality:
Reuse Existing Code
Polymorphism
Polymorphism means:
One Method
Many Behaviors
Example:
class Animal{
sound(){
console.log("Animal Sound");
}
}
Child:
class Dog extends Animal{
sound(){
console.log("Bark");
}
}
Another child:
class Cat extends Animal{
sound(){
console.log("Meow");
}
}
Now:
dog.sound();
Output:
Bark
And:
cat.sound();
Output:
Meow
Same method name.
Different behavior.
This is polymorphism.
DOM (Document Object Model)
When a browser loads an HTML page, it doesn't directly work with raw HTML.
Instead, the browser converts the HTML into a structure called:
Document Object Model (DOM)
The DOM represents the webpage as a tree of objects.
Example HTML:
<html>
<body>
<h1>Hello World</h1>
</body>
</html>
Browser creates:
Document
|
html
|
body
|
h1
JavaScript can access and modify these elements dynamically.
Why DOM Exists
Imagine a website where users can:
- Click buttons
- Open menus
- Submit forms
- Add products to cart
Without the DOM, JavaScript would have no way to interact with webpage elements.
Accessing Elements
const heading =
document.getElementById("title");
Example:
<h1 id="title">
Welcome
</h1>
JavaScript:
const heading =
document.getElementById("title");
heading.innerText =
"Welcome to WhosGeek";
Output:
<h1>
Welcome to WhosGeek
</h1>
The page changes instantly.
Real World Example
Suppose an e-commerce website displays:
Cart Items: 2
When a user adds another product:
cartCount.innerText = 3;
The DOM updates the page without reloading.
Common DOM Methods
getElementById()
document.getElementById("title");
querySelector()
document.querySelector(".card");
Returns first matching element.
querySelectorAll()
document.querySelectorAll(".card");
Returns all matching elements.
createElement()
const div =
document.createElement("div");
Creates a new DOM element.
appendChild()
parent.appendChild(child);
Adds an element to the page.
Event Handling
Websites become interactive through events.
Examples:
- Click
- Mouse Hover
- Keyboard Input
- Form Submission
Example:
button.addEventListener(
"click",
function(){
alert("Button Clicked");
}
);
Real World Example
When a user clicks:
Add To Cart
An event listener runs.
That event updates:
- Cart count
- Price
- Product list
This is event-driven programming.
BOM (Browser Object Model)
Many beginners confuse:
DOM
and
BOM
They are different.
DOM
Controls:
HTML Elements
Examples:
document.getElementById()
document.querySelector()
BOM
Controls:
Browser Features
Examples:
window
navigator
location
history
screen
window Object
Everything inside the browser exists under:
window
Example:
console.log(window);
The browser prints a massive object.
Alert Box
window.alert(
"Welcome"
);
Usually written as:
alert("Welcome");
Because JavaScript automatically uses window.
Location Object
Provides information about the current URL.
Example:
console.log(
location.href
);
Output:
https://example.com
Redirect User
location.href =
"https://google.com";
Browser navigates to another page.
Navigator Object
Provides browser information.
Example:
console.log(
navigator.userAgent
);
Can reveal:
- Browser
- Device
- Operating System
localStorage
Web applications often need to store data.
Example:
- Theme settings
- Login preferences
- Shopping cart
One solution is:
localStorage
What Is localStorage?
localStorage stores data permanently inside the browser.
Data remains available:
- After refresh
- After closing browser
- After restarting system
Until manually removed.
Store Data
localStorage.setItem(
"username",
"Alex"
);
Read Data
console.log(
localStorage.getItem(
"username"
)
);
Output:
Alex
Remove Data
localStorage.removeItem(
"username"
);
Real World Example
Dark Mode Preference
localStorage.setItem(
"theme",
"dark"
);
When user revisits website:
const theme =
localStorage.getItem(
"theme"
);
Website remembers preference.
sessionStorage
Very similar to localStorage.
Main difference:
Data disappears when tab closes
Store Data
sessionStorage.setItem(
"token",
"123"
);
Read Data
sessionStorage.getItem(
"token"
);
localStorage vs sessionStorage
| Feature | localStorage | sessionStorage |
|---|---|---|
| Persists After Browser Restart | ✅ | ❌ |
| Persists After Refresh | ✅ | ✅ |
| Shared Across Tabs | ✅ | ❌ |
| Storage Limit | ~5MB | ~5MB |
Cookies
Before localStorage existed, websites mainly used cookies.
Cookies are small pieces of data stored by browsers.
Create Cookie
document.cookie =
"name=Alex";
Why Cookies Exist
Common Uses:
- Authentication
- User Preferences
- Session Management
Real World Example
After login:
document.cookie =
"sessionId=abc123";
Server recognizes user on future requests.
Cookies vs localStorage
| Feature | Cookie | localStorage |
|---|---|---|
| Sent to Server Automatically | ✅ | ❌ |
| Storage Size | Small | Larger |
| Used For Authentication | Common | Rare |
| Expiration Support | ✅ | Manual |
IndexedDB
Sometimes:
5MB
is not enough.
Applications may need:
- Offline Data
- Large Storage
- Complex Data
This is where IndexedDB helps.
What Is IndexedDB?
IndexedDB is a browser database.
It can store:
- Objects
- Files
- Large datasets
Unlike localStorage:
localStorage
stores strings only.
IndexedDB stores structured data.
Real World Examples
Applications using IndexedDB:
- Gmail Offline
- Google Docs Offline
- Notion
- Trello
Understanding the JavaScript Event Loop
This is one of the most important JavaScript interview topics.
Many developers memorize answers without understanding the mechanism.
Let's simplify it.
Is JavaScript Single Threaded?
Yes.
JavaScript executes one task at a time.
Think of a restaurant with only one chef.
The chef can cook only one dish at a time.
Similarly:
JavaScript
=
Single Thread
Call Stack
The Call Stack tracks function execution.
Example:
function one(){
two();
}
function two(){
console.log("Hello");
}
one();
Execution:
Call Stack
one()
two()
console.log()
Functions enter stack.
After execution they leave.
The Problem
Suppose:
setTimeout(()=>{
console.log("Hi");
},1000);
JavaScript should not stop everything for 1 second.
Otherwise websites become frozen.
Web APIs
Browser provides:
Web APIs
Examples:
- setTimeout
- fetch
- DOM Events
When JavaScript sees:
setTimeout()
Browser handles timing.
JavaScript continues execution.
Callback Queue
After timer completes:
setTimeout(...)
moves callback into:
Callback Queue
Event Loop
Event Loop constantly checks:
Is Call Stack Empty?
If yes:
Move callback from queue to stack.
This process creates asynchronous behavior.
Visual Flow
Call Stack
↓
Web APIs
↓
Callback Queue
↓
Event Loop
↓
Call Stack
Promises in JavaScript
Before Promises, developers heavily used:
callbacks
This often created:
Callback Hell
Example:
getUser(function(){
getOrders(function(){
getPayment(function(){
});
});
});
Hard to read.
Hard to maintain.
What Is a Promise?
A Promise represents:
Future Result
States:
- Pending
- Fulfilled
- Rejected
Example
const promise =
new Promise(
(resolve,reject)=>{
resolve("Success");
});
Consuming Promise
promise.then(data=>{
console.log(data);
});
Output:
Success
Async Await
ES2017 introduced:
async
await
Making asynchronous code easier.
Promise Version
fetchData()
.then(data=>{
console.log(data);
});
Async Await Version
async function getData(){
const result =
await fetchData();
console.log(result);
}
Much cleaner.
Much easier to read.
Why Developers Prefer Async/Await
Benefits:
- Cleaner code
- Better readability
- Easier debugging
- Less nesting
- Better maintenance

0 Comments