The Small Word That Creates Big Confusion
If you ask JavaScript developers which concept confused them the most when they were beginners, many will mention one word:
this
It's only four letters.
Yet it causes thousands of questions every year.
I remember seeing code like this:
const user = {
name: "Aqad",
greet() {
console.log(this.name);
}
};
user.greet();
Output:
Aqad
Simple enough.
Then I tried something slightly different.
const greetUser = user.greet;
greetUser();
And suddenly:
undefined
Or in some cases:
TypeError
My immediate reaction was:
"Wait, it's the same function."
"Why did the result change?"
The answer lies in understanding how JavaScript determines the value of:
this
And once you understand that, Call, Apply, and Bind become much easier.
Understanding this Through an Employee ID Card
Imagine a company with several employees.
Each employee has an ID card.
Example:
Employee A
ID: 101
Employee B
ID: 102
Employee C
ID: 103
Now imagine someone says:
"Show me YOUR ID card."
The answer depends entirely on who is holding the card.
The word:
YOUR
changes depending on the person.
Similarly:
this
does not have a fixed value.
Its value depends on how a function is called.
This is the most important thing to remember.
What Is this?
A simple definition:
thisrefers to the object that is currently executing the function.
Notice something important.
Not where the function was created.
Not where it was written.
But:
How it is called.
This rule explains most this behavior.
First Example
const vendor = {
company: "Fresh Foods",
showCompany() {
console.log(this.company);
}
};
vendor.showCompany();
Output:
Fresh Foods
Why?
Because:
vendor.showCompany();
means:
vendor is calling the function
Therefore:
this === vendor
Visualizing It
Think:
vendor
|
+---- showCompany()
When:
vendor.showCompany();
runs:
JavaScript says:
this = vendor
Therefore:
this.company
becomes:
vendor.company
Result:
Fresh Foods
Another Example
const retailer = {
company: "Retail World",
showCompany() {
console.log(this.company);
}
};
retailer.showCompany();
Output:
Retail World
Same function structure.
Different object.
Different this.
The Rule Most Beginners Miss
Many beginners think:
this belongs to the function
Wrong.
this belongs to the execution context created during the function call.
The same function can have different values of this.
Losing Context
Consider:
const user = {
name: "Aqad",
greet() {
console.log(this.name);
}
};
Works:
user.greet();
Output: Aqad
Now:
const greetFunction = user.greet;
greetFunction();
Output: undefined
Why?
Because: greetFunction();
is not called by:
user
anymore.
The connection was lost.
Real-Life Analogy
Imagine an employee removes their ID card and places it on a table.
Someone asks:
"Whose ID is this?"
Nobody knows anymore.
The identity connection is gone.
Similarly:
const greetFunction = user.greet;
removes the function from its original object.
Now JavaScript doesn't know which object should become this.
Why Call, Apply, and Bind Exist
Developers often want control.
Instead of letting JavaScript decide:
this
we sometimes want to explicitly specify it.
That's exactly why JavaScript provides:
call()
apply()
bind()
Think of them as tools for assigning an identity card manually.
Understanding call()
Imagine a company manager says:
"Execute this task as Employee A."
That's what call() does.
Example:
function greet() {
console.log(this.name);
}
Objects:
const userOne = {
name: "Aqad"
};
Using call:
greet.call(userOne);
Output: Aqad
Why?
Because:
call()
explicitly sets:
this = userOne
Visualizing call()
Without call: greet();
JavaScript decides.
With call: greet.call(userOne);
You decide.
Passing Arguments with call()
Example:
function greet(city) {
console.log(
this.name,
city
);
}
Using:
greet.call(
{ name: "Aqad" },
"Bangalore"
);
Output: Aqad Bangalore
Syntax:
functionName.call(
thisValue,
arg1,
arg2,
arg3
);
Arguments are passed individually.
Understanding apply()
apply() is almost identical to call().
The only difference is how arguments are passed.
Example:
function greet(city, country) {
console.log(
this.name,
city,
country
);
}
Using:
greet.apply(
{ name: "Aqad" },
["Bangalore", "India"]
);
Output: Aqad Bangalore India
Notice: Arguments are passed as an array.
Call vs Apply
call()
greet.call(
user,
"Bangalore",
"India"
);
apply()
greet.apply(
user,
["Bangalore", "India"]
);
Everything else is almost the same.
Why apply() Was Useful
Before the spread operator existed:
Developers frequently used:
apply()
to pass arrays as arguments.
Today:
...
has reduced many apply() use cases.
But you should still understand it because it appears in older codebases and interviews.
Understanding bind()
Now comes the most powerful one.
Imagine you want to permanently assign an employee ID card.
Not execute immediately.
Just create the association for future use.
That's what:
bind()
does.
Example
function greet() {
console.log(this.name);
}
Object:
const user = {
name: "Aqad"
};
Bind:
const newFunction =
greet.bind(user);
Nothing happens yet.
Important:
bind()
does NOT execute the function.
It creates a new function.
Execution:
newFunction();
Output:
Aqad
Real Difference
call()
Executes immediately.
greet.call(user);
apply()
Executes immediately.
greet.apply(user);
bind()
Returns a new function.
const fn =
greet.bind(user);
fn();
Executes later.
A Delivery Driver Analogy
Imagine a delivery driver.
call()
Deliver this package now.
apply()
Deliver this package now
with instructions list.
bind()
Here is tomorrow's delivery assignment.
Use it later.
This analogy helps many developers remember the difference.
Real World Example: Event Handlers
Imagine:
const vendor = {
company: "Fresh Foods",
showCompany() {
console.log(this.company);
}
};
Later:
button.onclick =
vendor.showCompany;
Problem:
this
may no longer refer to:
vendor
Solution:
button.onclick =
vendor.showCompany.bind(vendor);
Now:
this
always remains:
vendor
This pattern appears frequently in frontend development.
AQAD Marketplace Example
Imagine:
const retailer = {
name: "Retail World",
generateInvoice() {
console.log(
this.name
);
}
};
If:
generateInvoice
is passed around the application,
the original context may be lost.
Using:
bind()
ensures:
this.name
always refers to the retailer.
Common Interview Question
What is the output?
const user = {
name: "Aqad",
greet() {
console.log(this.name);
}
};
const fn = user.greet;
fn();
Output: undefined
Because:
this
lost its original context.
Fix:
const fn =
user.greet.bind(user);
fn();
Output: Aqad
Common Beginner Mistakes
Mistake 1
Thinking this belongs to the function.
It doesn't.
It depends on how the function is called.
Mistake 2
Confusing call() and bind()
Remember:
call → execute now
bind → execute later
Mistake 3
Ignoring lost context
Many bugs happen because:
this
changes unexpectedly.
Always verify how the function is being called.
Modern JavaScript and Arrow Functions
You may wonder:
"Why do I see arrow functions everywhere?"
One major reason is that arrow functions handle:
this
differently.
Example:
const greet = () => {
console.log(this);
};
Arrow functions do not create their own this.
Instead:
They inherit it from the surrounding scope.
We'll discuss this further in the ES6 chapter.
For now, just remember:
Regular Functions → own this
Arrow Functions → inherited this
Why Senior Developers Care About This Topic
Understanding:
this
helps with:
React applications
Event handlers
Node.js development
Object-oriented programming
Framework internals
Interview questions
Many JavaScript bugs ultimately come down to:
Wrong value of this
Once you understand how JavaScript assigns context, those bugs become much easier to solve.
Summary we learned:
What
thisisHow JavaScript determines
thisContext loss
call()
apply()
bind()
Differences between them
Real-world examples
Common interview questions
Event handler use cases
Think of this as an employee ID card.
The value depends on who is currently holding the card.
Sometimes JavaScript assigns the identity automatically.
Other times we assign it manually using:
call()
apply()
bind()
These tools give us complete control over function context.
And now that we've covered many of JavaScript's core concepts, it's time to explore the language features that transformed modern JavaScript development.
Features that made code shorter, cleaner, and easier to maintain.
ES6 Features That Changed JavaScript Forever
The Day JavaScript Grew Up
If you started learning JavaScript recently, you probably take certain features for granted.
Things like:
const name = "Aqad";
const greet = () => {
console.log("Hello");
};
look completely normal.
But there was a time when none of this existed.
Back then, JavaScript developers wrote code like:
var name = "Aqad";
function greet() {
console.log("Hello");
}
Applications were growing larger.
Teams were growing larger.
And JavaScript needed better tools.
In 2015, a major update arrived.
Officially called:
ECMAScript 2015
But most developers simply call it:
ES6
This update transformed JavaScript forever.
In many ways:
JavaScript Before ES6
and
JavaScript After ES6
feel like two different worlds.
Let's explore the features that every modern developer uses almost every day.
Why ES6 Was Such A Big Deal
Imagine running a growing company.
Initially:
5 Employees
Simple processes work fine.
But as the company grows:
500 Employees
you need:
Better systems
Better organization
Better communication
JavaScript faced the same problem.
Web applications became larger.
Developers needed cleaner and safer ways to write code.
ES6 provided those solutions.
Feature 1: let and const
Before ES6, developers mostly used:
var
We already learned that var can create confusing behavior.
Example:
if (true) {
var city = "Dubai";
}
console.log(city);
Output:
Dubai
The variable leaks outside the block.
This caused many bugs in large applications.
Enter let
let city = "Dubai";
Example:
if (true) {
let city = "Dubai";
}
console.log(city);
Output: ReferenceError
Because:
let is block scoped
This makes code more predictable.
Enter const
When a value should never change:
const company = "AQAD";
Example:
company = "Google";
Output:
TypeError
JavaScript protects the value.
Modern Rule
Most professional developers follow:
Use const by default.
Use let when values change.
Avoid var.
You'll see this pattern in almost every modern codebase.
Feature 2: Arrow Functions
Before ES6:
function greet() {
console.log("Hello");
}
Works perfectly.
But sometimes the syntax becomes repetitive.
ES6 introduced:
const greet = () => {
console.log("Hello");
};
This is called an Arrow Function.
Why Developers Love Arrow Functions
Compare:
Traditional:
function add(a, b) {
return a + b;
}
Arrow:
const add = (a, b) => {
return a + b;
};
Cleaner.
More compact.
Especially useful when working with arrays and callbacks.
Even Shorter Syntax
If there is only one expression:
const add = (a, b) => a + b;
Same result.
Less code.
Real World Example
Suppose we have:
const products = [
"Pepsi",
"Sprite",
"Fanta"
];
Traditional:
products.forEach(function(product) {
console.log(product);
});
Arrow:
products.forEach(product => {
console.log(product);
});
Most developers find the second version easier to read.
Feature 3: Template Literals
Before ES6:
const name = "Aqad";
console.log(
"Hello " + name
);
Works.
But becomes messy with larger strings.
ES6 Solution
const name = "Aqad";
console.log(
`Hello ${name}`
);
Output:
Hello Aqad
Much cleaner.
Why Template Literals Are Useful
Imagine displaying retailer information.
Without template literals:
const retailer = "Retail World";
const city = "Dubai";
console.log(
retailer +
" is located in " +
city
);
ES6 version:
console.log(
`${retailer} is located in ${city}`
);
Far easier to read.
Multi-Line Strings
Before ES6:
const text =
"Line One\n" +
"Line Two\n" +
"Line Three";
After ES6:
const text = `
Line One
Line Two
Line Three
`;
Much cleaner.
Feature 4: Destructuring
This is one of the most used ES6 features.
Imagine:
const vendor = {
company: "Fresh Foods",
country: "UAE",
city: "Dubai"
};
Without destructuring:
const company = vendor.company;
const country = vendor.country;
const city = vendor.city;
Works.
But repetitive.
ES6 Solution
const {
company,
country,
city
} = vendor;
Now:
console.log(company);
Output:
Fresh Foods
Much shorter.
Real Backend Example
API response:
const response = {
userId: 1,
name: "Aqad",
role: "Admin"
};
Instead of:
response.name
response.role
response.userId
Use:
const {
userId,
name,
role
} = response;
Very common in Node.js projects.
Array Destructuring
Example:
const colors = [
"Red",
"Blue",
"Green"
];
Instead of:
const first = colors[0];
const second = colors[1];
Use:
const [
first,
second
] = colors;
Output:
Red
Blue
Feature 5: Spread Operator (...)
One of the most useful ES6 additions.
Imagine:
const fruits = [
"Apple",
"Banana"
];
Copying manually:
const copy = [
fruits[0],
fruits[1]
];
Not ideal.
Spread Syntax
const copy = [
...fruits
];
Result:
[
"Apple",
"Banana"
]
Simple and clean.
Combining Arrays
Example:
const fruits = [
"Apple",
"Banana"
];
const vegetables = [
"Potato",
"Tomato"
];
Combine:
const items = [
...fruits,
...vegetables
];
Output:
[
"Apple",
"Banana",
"Potato",
"Tomato"
]
This pattern appears constantly in React and Node.js.
Spread With Objects
Example:
const vendor = {
company: "AQAD Vendor"
};
Create a new object:
const updatedVendor = {
...vendor,
country: "UAE"
};
Result:
{
company: "AQAD Vendor",
country: "UAE"
}
Very useful when updating state or API data.
Feature 6: Default Parameters
Before ES6:
function greet(name) {
name = name || "Guest";
console.log(name);
}
Developers used tricks like this.
ES6 Solution
function greet(
name = "Guest"
) {
console.log(name);
}
Usage: greet();
Output: Guest
Cleaner and easier to understand.
Feature 7: Rest Parameters
Imagine:
sum(10, 20, 30, 40);
How do we accept an unknown number of arguments?
ES6 provides:
function sum(...numbers) {
console.log(numbers);
}
Output: [10, 20, 30, 40]
Very useful when building utility functions.
Feature 8: Enhanced Object Literals
Before ES6:
const company = "AQAD";
const vendor = {
company: company
};
ES6:
const company = "AQAD";
const vendor = {
company
};
Same result.
Less code.
Feature 9: Modules
Before ES6, managing large applications was difficult.
Everything often ended up in one file.
As projects grew:
Chaos followed.
ES6 Modules
Export:
export const company =
"AQAD";
Import:
import {
company
} from "./config.js";
This allows code to be organized into separate files.
Modern applications rely heavily on modules.
Real World AQAD Example
Imagine:
auth.js
products.js
orders.js
payments.js
analytics.js
Each module handles its own responsibility.
This makes projects easier to manage.
Feature 10: Promises (Introduced in ES6)
We already covered Promises in detail.
But technically:
Promises were also one of the major ES6 additions.
Example:
fetchProducts()
.then(console.log)
.catch(console.error);
This changed how asynchronous JavaScript was written.
Why ES6 Changed Careers
Many developers who learned only old JavaScript struggled when modern frameworks appeared.
Frameworks like:
React
Vue
Angular
Next.js
Node.js Applications
heavily use ES6 features.
Understanding ES6 became a requirement for professional development.
Common Beginner Mistakes
Mistake 1
Using let everywhere.
Prefer:
const
when values don't change.
Mistake 2
Overusing arrow functions.
Regular functions are still useful.
Use the right tool for the job.
Mistake 3
Confusing Spread and Rest.
Remember:
Spread:
...array
expands values.
Rest:
function(...args)
collects values.
Why Senior Developers Love ES6
ES6 made JavaScript:
Cleaner
Safer
Easier to maintain
More expressive
More scalable
Many patterns that once required dozens of lines can now be written in just a few.
This improves productivity and reduces bugs.
Summary we learned:
let
const
Arrow Functions
Template Literals
Destructuring
Spread Operator
Rest Parameters
Default Parameters
Modules
Modern JavaScript Practices
Think of ES6 as a major upgrade to JavaScript's toolbox.
The language didn't change its identity.
It simply gained better tools for solving modern problems.
And now, after covering the most important JavaScript concepts from beginner to advanced, there's one final chapter left.
A chapter dedicated to helping you prepare for real-world jobs, coding interviews, and professional development.
JavaScript Interview Preparation — Questions, Concepts, and Real Developer Advice
Congratulations — You're Further Than You Think
take a moment and appreciate how far you've come.
When we started this roadmap, we talked about:
Variables
Data Types
Operators
Conditions
Functions
At that stage, JavaScript looked simple.
A few variables.
A few functions.
Some console logs.
Nothing too scary.
But as we continued, we explored topics that many developers struggle with for years:
Execution Context
Call Stack
Hoisting
Scope
Closures
Event Loop
Promises
Async Await
Call Apply Bind
ES6 Features
These aren't beginner topics.
These are the concepts that separate:
Someone who writes JavaScript
from
Someone who understands JavaScript
And that distinction matters.
Because interviews rarely test whether you can write:
let age = 25;
Instead, they test whether you understand what happens behind the scenes.
This final chapter is designed to prepare you for that reality.
Not just interviews.
But real-world development as well.
What Companies Actually Want
Many beginners imagine interviews look like this:
What is a variable?
What is a function?
What is an array?
Those questions may appear.
But most companies care more about:
Problem Solving
Debugging
Understanding
Communication
A senior interviewer is often trying to answer one question:
"Can this person work on a real project?"
That means understanding concepts matters more than memorizing definitions.
The Biggest Mistake Interview Candidates Make
Many candidates spend weeks memorizing answers.
Example:
Closure definition:
A closure is...
They memorize every word.
Then the interviewer asks:
"Can you explain closures using a real-world example?"
And suddenly they struggle.
Why?
Because memorization is not understanding.
If you truly understand a concept, you can explain it:
To a developer
To a student
To a manager
To a child
Using different examples.
That is the level you should aim for.
Question 1: What Is JavaScript?
Simple answer:
JavaScript is a high-level, interpreted programming language primarily used to create dynamic and interactive web applications.
Human answer:
JavaScript brings life to websites. HTML provides structure, CSS provides design, and JavaScript adds behavior and interaction.
Interviewers usually prefer the second style because it shows practical understanding.
Question 2: Difference Between var, let, and const
This question appears constantly.
var
Function Scoped
Can be redeclared
Can be reassigned
Hoisted
Example:
var name = "Aqad";
var name = "Ahmed";
Valid.
let
Block Scoped
Cannot be redeclared
Can be reassigned
Example:
let age = 25;
age = 30;
Valid.
const
Block Scoped
Cannot be redeclared
Cannot be reassigned
Example:
const company = "AQAD";
Preferred when values shouldn't change.
Question 3: What Is Hoisting?
Interview answer:
Hoisting is JavaScript's behavior of processing variable and function declarations during the memory creation phase before code execution begins.
Practical explanation:
JavaScript prepares memory before running code. Because of that preparation, variables and functions may appear accessible before their declaration line.
Question 4: What Is Scope?
Simple answer:
Scope determines where variables can be accessed.
Types:
Global Scope
Function Scope
Block Scope
Real-world analogy:
Scope is like room access inside a company. Some information is public. Some belongs only to a department. Some belongs only to a specific employee.
Interviewers love analogies because they demonstrate understanding.
Question 5: What Is a Closure?
One of the most famous questions.
Technical answer:
A closure occurs when a function remembers variables from its outer scope even after the outer function has completed execution.
Practical answer:
A closure is like an ATM card. Even after leaving the bank, the ATM still remembers your account information.
That explanation is easier to remember.
Question 6: What Is the Event Loop?
Many companies ask this.
Simple answer:
The Event Loop continuously checks whether the Call Stack is empty and moves completed callbacks from the queue into execution.
Restaurant explanation:
JavaScript acts like a waiter. Long-running tasks are sent to the kitchen. When food is ready, the Event Loop ensures it gets served at the right time.
Question 7: Difference Between == and ===
Example:
5 == "5"
Output:
true
Because type conversion happens.
Example:
5 === "5"
Output:
false
Because:
Number ≠ String
Professional developers usually prefer:
===
because it avoids unexpected bugs.
Question 8: What Is the Difference Between null and undefined?
undefined
Means: Value not assigned yet
Example:
let user;
console.log(user);
Output: undefined
null
Means: Intentionally empty
Example: let user = null;
Think: undefined → Unknown
null → Empty on purpose
Question 9: Explain Call, Apply, and Bind
call()
Executes immediately.
greet.call(user);
apply()
Executes immediately.
Arguments passed as an array.
greet.apply(user, ["Dubai"]);
bind()
Returns a new function.
const fn = greet.bind(user);
Executes later.
Question 10: What Is a Promise?
Simple answer:
A Promise represents the eventual success or failure of an asynchronous operation.
States:
Pending
Fulfilled
Rejected
Restaurant analogy:
A Promise is like a food order token. You don't receive the meal immediately, but you're guaranteed either success or failure later.
Question 11: What Is Async Await?
Simple answer:
Async Await is syntax built on top of Promises that makes asynchronous code easier to read and maintain.
Example:
const user = await getUser();
Feels like synchronous code while still remaining asynchronous.
Question 12: Explain the Call Stack
Simple answer:
The Call Stack tracks function execution using a Last In First Out (LIFO) structure.
Plate analogy:
Stack Plates
Add From Top
Remove From Top
JavaScript manages function execution similarly.
Common Coding Questions
Interviewers often ask small coding problems.
Examples:
Reverse a String
function reverseString(str) {
return str
.split("")
.reverse()
.join("");
}
Check Palindrome
function isPalindrome(str) {
return str ===
str.split("")
.reverse()
.join("");
}
Find Maximum Number
function max(arr) {
return Math.max(...arr);
}
Remove Duplicates
const unique = [
...new Set([1,1,2,3,3])
];
Output:
[1,2,3]
What Freshers Should Focus On
If you're preparing for your first job:
Master:
Variables
Functions
Arrays
Objects
Loops
Conditions
DOM Basics
ES6
Promises
Async Await
Many freshers jump directly into advanced frameworks.
That's a mistake.
Strong fundamentals make frameworks easier.
What Backend Developers Should Focus On
Since our next pillar article focuses on Node.js and backend development, these topics become important:
JavaScript Fundamentals
Event Loop
Async Await
Promises
APIs
HTTP
JSON
Authentication
Databases
Most Node.js interview questions eventually connect back to JavaScript fundamentals.
Real Advice From Industry Experience
If you're learning JavaScript for a career:
Don't try to memorize everything.
Build projects.
Because projects reveal knowledge gaps faster than tutorials.
Example projects:
Beginner
Calculator
Todo App
Weather App
Intermediate
E-Commerce Frontend
Expense Tracker
Chat Application
Advanced
Inventory Management System
Marketplace Platform
Order Management System
Real-Time Dashboard
Projects teach lessons that books cannot.
A Learning Roadmap After This Article
Once you're comfortable with JavaScript:
Move to:
HTML
CSS
JavaScript
↓
Git & GitHub
↓
React
↓
Node.js
↓
Express
↓
MySQL / PostgreSQL
↓
Authentication
↓
Deployment
↓
Cloud Platforms
This path mirrors how many full-stack developers grow professionally.
The Truth About Becoming a JavaScript Developer
Many beginners think professional developers know everything.
The reality is different.
Most experienced developers:
Forget syntax
Search documentation
Read Stack Overflow
Use Google
Use MDN
Learn continuously
The difference is not perfect memory.
The difference is understanding.
Once you understand concepts like:
Scope
Closures
Event Loop
Promises
Async Await
learning new tools becomes much easier.
Final Thoughts
JavaScript is often described as a simple language.
And at first glance, it is.
You can write your first JavaScript program in minutes.
But beneath that simplicity lies a fascinating system:
Execution Contexts
Memory Creation
Call Stack
Scope Chains
Closures
Event Loop
Asynchronous Operations
Understanding these concepts transforms the way you think about programming.
The goal of this roadmap was never to help you memorize JavaScript.
The goal was to help you understand it.
Because technologies change.
Frameworks change.
Libraries change.
But strong fundamentals remain valuable for decades.
Invest in those fundamentals, and every future technology becomes easier to learn.
What's Next?
Now that you've built a strong JavaScript foundation, the natural next step is:
Pillar Article 2
Node.js From Beginner to Backend Developer
We'll explore:
What Node.js actually is
Why Node.js was created
How V8 works
Event Loop inside Node.js
Modules
NPM
File System
Streams
Buffers
Express.js
Building Real APIs
Real Backend Architecture
And we'll continue using the same style:
Simple English
Story-Based Learning
Human Written Feel
Real Industry Examples
SEO Optimized Structure
Because the goal isn't just learning JavaScript.
The goal is becoming a confident Full Stack Developer.

0 Comments