JavaScript Course Content:
- Introduction
- Pre-requisites
- Data Types
- Strings
- Operators
- Variables
- Arrays
- Conditional statements (if, else, else if and Switch Statements)
- Loops (For, While, For-in, For-of)
- Use Strict
- Objects
- Functions
- Numbers
- Booleans
- Comparison and Logical Operators
- Break and Continue
- Iterables
- Sets and Set Methods
- Maps
- Classes and Inheritance
- Static Methods
- Callbacks
- Asynchronous JavaScript
- Promises
- Async/Await
Introduction
History of JavaScript[1995]
- JavaScript was created by Brendan Eich while working at Netscape Communications.
- It was initially named Mocha, then LiveScript, and finally JavaScript (to capitalize on Java’s popularity).
- JavaScript was designed in just 10 days and first appeared in Netscape Navigator 2.0.
Standardization - ECMAScript (1997)
Netscape submitted JavaScript to ECMA (European Computer Manufacturers Association) for standardization.
It was standardized in 1997 by European Computer Manufacturers Association (ECMA) and officially known as ECMAScript.
In 1997, ECMAScript (ES1) was released as the official standard for JavaScript.
JavaScript versions
- The latest version of JS is 4.30.0(March 21, 2025)
JavaScript is used for web, mobile (React Native), desktop (Electron), and even AI and IoT.
JavaScript started as a small scripting language but has evolved into one of the most powerful and widely used languages in the world.
Netscape submitted JavaScript to ECMA (European Computer Manufacturers Association) for standardization.
It was standardized in 1997 by European Computer Manufacturers Association (ECMA) and officially known as ECMAScript.
In 1997, ECMAScript (ES1) was released as the official standard for JavaScript.
JavaScript versions
- The latest version of JS is 4.30.0(March 21, 2025)
JavaScript is used for web, mobile (React Native), desktop (Electron), and even AI and IoT.
JavaScript started as a small scripting language but has evolved into one of the most powerful and widely used languages in the world.
JavaScript Reserved Words
JavaScript Comments
Not all JavaScript statements are "executed".
Code after double slashes //
or between /*
and */
is treated as a comment.
Comments are ignored, and will not be executed:
let x = 5; // I will be executed
// x = 6; I will NOT be executed
JavaScript Identifiers / Names
Identifiers are JavaScript names.
Identifiers are used to name variables and keywords, and functions.
The rules for legal names are the same in most programming languages.
A JavaScript name must begin with:
- A letter (A-Z or a-z)
- A dollar sign ($)
- Or an underscore (_)
Subsequent characters may be letters, digits, underscores, or dollar signs.
Note
Numbers are not allowed as the first character in names.
This way JavaScript can easily distinguish identifiers from numbers.
JavaScript is Case Sensitive
All JavaScript identifiers are case sensitive.
JavaScript Naming Conventions:
✅ 1. Class Names
-
Convention:
PascalCase
-
Definition: Every word starts with a capital letter and no underscores or hyphens.
-
Purpose: Used to define blueprints for objects (like user profiles, orders, etc.).
-
Example
class UserProfile {
constructor(name) {
this.name = name;
}
}
✅ 2. Method Names
-
Convention: camelCase
-
Definition: Starts with a lowercase letter, each subsequent word starts with a capital letter.
-
Purpose: Represents actions or behaviors an object can perform.
Convention: camelCase
Definition: Starts with a lowercase letter, each subsequent word starts with a capital letter.
Purpose: Represents actions or behaviors an object can perform.
Example
class Calculator {
addNumbers(a, b) {
return a + b;
}
}
class Calculator {
addNumbers(a, b) {
return a + b;
}
}
✅ 3. Variable Names
-
Convention: camelCase
-
Definition: Similar to methods—starts with lowercase, capitalizes each new word.
-
Purpose: Used to store data values such as numbers, strings, or objects
Convention: camelCase
Definition: Similar to methods—starts with lowercase, capitalizes each new word.
Purpose: Used to store data values such as numbers, strings, or objects
Example
let userAge = 25;
const isLoggedIn = true;
let userAge = 25;
const isLoggedIn = true;
✅ 4. File Names
-
Convention:
-
For regular modules/files: kebab-case
-
For React components: PascalCase.js
-
Definition:
-
kebab-case
: all lowercase letters with hyphens separating words.
-
PascalCase
: each word capitalized, no spaces or hyphens.
-
Purpose: Organizes source files; improves readability and maintainability.
-
Examples:
-
user-service.js
(module)
-
UserProfile.js
(React component)
-
dateUtils.js
(utility module)
Convention:
-
For regular modules/files:
kebab-case
-
For React components:
PascalCase.js
Definition:
-
kebab-case
: all lowercase letters with hyphens separating words. -
PascalCase
: each word capitalized, no spaces or hyphens.
Purpose: Organizes source files; improves readability and maintainability.
Examples:
-
user-service.js
(module) -
UserProfile.js
(React component) -
dateUtils.js
(utility module)
✅ 5. Constants
-
Convention: UPPER_SNAKE_CASE
-
Definition: All uppercase letters, words separated by underscores.
-
Purpose: Used for values that should never change (true constants).
Convention: UPPER_SNAKE_CASE
Definition: All uppercase letters, words separated by underscores.
Purpose: Used for values that should never change (true constants).
Example
const MAX_USERS = 100;
✅ 6. Private Fields
-
Convention: #camelCase
(ES2022+)
-
Definition: Prefix a field name with #
to make it truly private inside a class.
-
Purpose: Used to restrict access to data within the class scope.
Convention: #camelCase
(ES2022+)
Definition: Prefix a field name with #
to make it truly private inside a class.
Purpose: Used to restrict access to data within the class scope.
Example
class BankAccount {
#balance = 0;
deposit(amount) {
this.#balance += amount;
}
}
class BankAccount {
#balance = 0;
deposit(amount) {
this.#balance += amount;
}
}
JavaScript Output [Display Possibilities]
JavaScript can "display" data in different ways:
- Writing into an HTML element, using
innerHTML
orinnerText
. - Writing into the HTML output using
document.write()
. - Writing into an alert box, using
window.alert()
. - Writing into the browser console, using
console.log()
.
Pre-requisites
- Download & Install Node JS
- Visual Studio Code[VS Code]
- Open Command Prompt (CMD) or PowerShell.
- Type the following command and press Enter to check the Node.js version:
Step 2: Run the Installer
-
Locate the downloaded
.msi
file (usually in the Downloads folder).
Double-click to run the installer.
Step 3: Follow the Installation Wizard
-
Click Next on the welcome screen.
Accept the license agreement and click Next.
-
Choose the installation location (default is fine) and click Next.
-
Ensure that "Node.js runtime" and "npm package manager" are selected, then click Next.
- Click Install and wait for the process to complete.
- Click on Finish.
Step 4: Verify the Installation
-
Open Command Prompt (CMD) or PowerShell.
-
Type the following command and press Enter to check the Node.js version:
✅ If installed correctly, you'll see the Node.js version (e.g.,
v18.17.1
). -
To check the npm (Node Package Manager) version, type:
- Open your web browser and type download visual studio code.
- Click on the "Download for Windows" button.
The installer (
.exe
file) will start downloading automatically.
Step 2: Run the Installer
-
Locate the downloaded
.exe
file (usually in the Downloads folder). Double-click the file to launch the installer.
Step 3: Follow the Installation Wizard
-
Click Next on the welcome screen.
Accept the license agreement and click Next.
3.Choose the installation location (default is fine) and click Next.
Click Next on the welcome screen.
Accept the license agreement and click Next.
Step 4: Launch VS Code
1.Once installed, check "Launch Visual Studio Code" and click Finish.
2.VS Code will open. 🎉
=================================================
JavaScript Data Types
In JavaScript, data types define the kind of values a variable can hold. JavaScript is a dynamically-typed language, meaning that the type of a variable can change at runtime. There are 8 fundamental data types in JavaScript, which can be categorized into primitive and non-primitive types.
1. Primitive Data Types
Primitive data types are the most basic types in JavaScript. These include:
- string
- number
- bigint
- boolean
- undefined
- symbol
- null
These are called "primitive" because they are immutable (cannot be changed) and are passed by value.
string
A string is a sequence of characters enclosed in quotes (single, double, or backticks).
Example:
let name = "Alice";
let greeting = 'Hello, ' + name; // String concatenation
console.log(greeting); // Output: Hello, Alice
// Template literals (backticks)
let message = `Welcome, ${name}!`; // String interpolation
console.log(message); // Output: Welcome, Alice!
number
The number type in JavaScript represents both integer and floating-point values.
Example:
let age = 30; // Integer
let price = 99.99; // Floating point number
let hexValue = 0xFF; // Hexadecimal (255 in decimal)
let binary = 0b1010; // Binary (10 in decimal)
let octal = 0o12; // Octal (10 in decimal)
console.log(age); // 30
console.log(price); // 99.99
console.log(hexValue); // 255
console.log(binary); // 10
console.log(octal); // 10
JavaScript uses floating-point arithmetic for all numbers, even integers. Be careful with precision when using very large or very small numbers.
bigint
The BigInt type can represent integers with arbitrary precision. It is used for large numbers beyond the safe integer limit for regular numbers.
Example:
Number.MAX_SAFE_INTEGER
(which is 2^53 - 1).boolean
A boolean can only be one of two values: true
or false
. It is typically used in conditional statements.
Example:
if
, while
, and for
.undefined
A variable that is declared but not assigned a value automatically has the value undefined
. It is also the return value of functions that do not explicitly return anything.
Example:
null
The null type represents the intentional absence of any value. It is often used to indicate that a variable is empty or should hold an object later.
Example:
symbol
A symbol is a unique and immutable primitive value that can be used as the key for object properties. Each symbol is guaranteed to be unique.
A Symbol
is a primitive data type introduced in ES6 (ES2015). It's created using the Symbol()
function.
Example:
🔸 Why use Symbol?
Symbols are mainly used to:
-
Avoid property name conflicts in objects.
-
Create hidden (non-enumerable) properties.
-
Implement internal object behaviors (e.g., with built-in symbols like
Symbol.iterator
).
🔹 Global Symbols: Symbol.for()
You can use Symbol.for()
to create shared symbols that are registered globally.
Example:
let globalSym1 = Symbol.for("userId");
let globalSym2 = Symbol.for("userId");
console.log(globalSym1 === globalSym2); // true
Unlike Symbol()
, Symbol.for()
reuses the same symbol if the key already exists.
Here's a list of JavaScript data types along with what you get when you use the typeof
operator on them:
2.Non-Primitive Data Type (object)
An object is a non-primitive data type that can hold collections of key-value pairs. Unlike primitive types, objects are mutable and passed by reference.
Example:
Objects are often used to represent real-world entities with properties and methods.
Array
An array is a special type of object used to store ordered collections of data. Arrays can hold values of different data types.
Example:
Arrays have additional methods like push()
, pop()
, shift()
, unshift()
, and others to manipulate the collection.
🔹 Non-Primitive (Objects)
🧠 Quick Notes
-
typeof null
is"object"
— this is a known JavaScript bug from its early days. -
typeof NaN
is"number"
— because NaN stands for "Not a Number" but still has typenumber
. -
Arrays and Dates return
"object"
, so to check if something is an array, useArray.isArray(arr)
Quiz: JavaScript Data Types
1. What will be the output of the following code?
- a)
5
,10
- b)
10
,10
- c)
5
,5
- d)
10
,5
Answer: a) 5
, 10
Explanation: Since a
is a primitive value (number), when b
is assigned to a
, b
holds a copy of a
. Changing b
does not affect a
.
- a)
undefined
- b)
object
- c)
boolean
- d)
symbol
Answer: d) symbol
Explanation: The typeof
operator returns symbol
for values of the Symbol
data type.
- a)
1
- b)
2
- c)
3
- d)
undefined
Answer: c) 3
Explanation: Since objects are passed by reference, modifying obj2
also modifies obj
because they refer to the same object in memory.
- a)
true
- b)
false
- c)
null
- d)
undefined
Answer: b) false
Explanation: null
and undefined
are distinct values in JavaScript, so x === undefined
evaluates to
5. What is the result of the following?
✅ 1. What is a Function?
Definition:
A function in JavaScript is a reusable block of code designed to perform a specific task. It can take inputs, process them, and return a result.
Key Points:
-
Promotes code reusability
-
Helps keep code modular and readable
-
Can accept parameters and return values
A function in JavaScript is a reusable block of code designed to perform a specific task. It can take inputs, process them, and return a result.
Promotes code reusability
Helps keep code modular and readable
Can accept parameters and return values
Example
function greet(name) {
console.log("Hello, " + name + "!");
}
greet("John"); // Output: Hello, John!
function greet(name) {
console.log("Hello, " + name + "!");
}
greet("John"); // Output: Hello, John!
✅ 2. Function Declaration
Definition:
A function declaration (also called a function statement) defines a named function using the function
keyword.
Key Points:
-
Hoisted to the top of their scope, so they can be called before being declared
-
Best for defining reusable named logic
Syntax
function functionName(parameters) {
// code to execute
}
function functionName(parameters) {
// code to execute
}
Example
sayHello(); // Allowed due to hoisting
function sayHello() {
console.log("Hello!");
}
sayHello(); // Allowed due to hoisting
function sayHello() {
console.log("Hello!");
}
✅ 3. Function Expression
Definition:
A function expression is when a function is assigned to a variable.
Key Points:
-
Not hoisted; cannot be called before it's defined
-
Can be anonymous or named
Example
const add = function(a, b) {
return a + b;
};
console.log(add(5, 3)); // Output: 8
const add = function(a, b) {
return a + b;
};
console.log(add(5, 3)); // Output: 8
✅ 4. Calling a Function
Definition:
To call (invoke) a function means to execute the code inside it.
Key Points:
-
Use parentheses ()
to call a function
-
You can pass arguments inside the parentheses
To call (invoke) a function means to execute the code inside it.
Use parentheses ()
to call a function
You can pass arguments inside the parentheses
Example
function greet() {
console.log("Welcome!");
}
greet(); // Output: Welcome!
function greet() {
console.log("Welcome!");
}
greet(); // Output: Welcome!
With arguments:
function sum(a, b) {
console.log(a + b);
}
sum(2, 3); // Output: 5
function sum(a, b) {
console.log(a + b);
}
sum(2, 3); // Output: 5
✅ 5. Return Statement
Definition:
The return
statement ends function execution and specifies a value to be returned to the caller.
Key Points:
-
After return
, function exits immediately
-
Useful when you want to get a result back
The
return
statement ends function execution and specifies a value to be returned to the caller.After return
, function exits immediately
Useful when you want to get a result back
Example
function multiply(a, b) {
return a * b;
}
const result = multiply(4, 5);
console.log(result); // Output: 20
function multiply(a, b) {
return a * b;
}
const result = multiply(4, 5);
console.log(result); // Output: 20
✅ 6. Function Parameters vs Arguments
Definition:
-
Parameters are the named variables in a function definition.
-
Arguments are the actual values passed to the function when it is called.
Key Points:
-
Parameters are like placeholders.
-
Arguments are real values.
Parameters are the named variables in a function definition.
Arguments are the actual values passed to the function when it is called.
Parameters are like placeholders.
Arguments are real values.
Example
function welcome(user) { // 'user' is a parameter
console.log("Welcome, " + user);
}
welcome("Alice"); // "Alice" is an argument
// Output: Welcome, Alice
function welcome(user) { // 'user' is a parameter
console.log("Welcome, " + user);
}
welcome("Alice"); // "Alice" is an argument
// Output: Welcome, Alice
Types of Functions
-
Anonymous Functions
-
Named Functions
-
Arrow Functions (
=>
) -
Immediately Invoked Function Expressions (IIFE)
-
Generator Functions (
function*
) -
Async Functions (
async/await
)
✅ 1. Named Functions
A named function has a name when it's declared and can be reused multiple times.
Example
function greet() {
console.log("Hello, World!");
}
greet(); // Output: Hello, World!
function greet() {
console.log("Hello, World!");
}
greet(); // Output: Hello, World!
Use case: Good for reusable logic and stack trace readability in debugging.
✅ 2. Anonymous Functions
Functions without a name. Often used as arguments to other functions or assigned to variables.
Example
const sayHi = function() {
console.log("Hi!");
};
sayHi(); // Output: Hi!
const sayHi = function() {
console.log("Hi!");
};
sayHi(); // Output: Hi!
Use case: Useful for passing as callbacks (e.g., in setTimeout
, .map()
etc.)
✅ 3. Arrow Functions (=>
)
Shorter syntax for writing function expressions. Arrow functions do not bind their own this
.
Example
const add = (a, b) => a + b;
console.log(add(5, 3)); // Output: 8
const add = (a, b) => a + b;
console.log(add(5, 3)); // Output: 8
Multiline syntax:
const greet = (name) => {
console.log("Hello, " + name);
};
greet("Alex"); // Output: Hello, Alex
const greet = (name) => {
console.log("Hello, " + name);
};
greet("Alex"); // Output: Hello, Alex
Note: Avoid arrow functions for object methods if you need access to this
.
✅ 4. IIFE (Immediately Invoked Function Expression)
A function that runs immediately after it's defined.
Example
(function () {
console.log("IIFE executed");
})();
(function () {
console.log("IIFE executed");
})();
Or with arrow function:
(() => {
console.log("Arrow IIFE executed");
})();
(() => {
console.log("Arrow IIFE executed");
})();
Use case: Used to create a private scope and avoid polluting the global namespace.
✅ 5. Generator Functions (function*
)
Special functions that can pause and resume execution using the yield
keyword.
Example
function* count() {
yield 1;
yield 2;
yield 3;
}
const counter = count();
console.log(counter.next().value); // 1
console.log(counter.next().value); // 2
console.log(counter.next().value); // 3
function* count() {
yield 1;
yield 2;
yield 3;
}
const counter = count();
console.log(counter.next().value); // 1
console.log(counter.next().value); // 2
console.log(counter.next().value); // 3
Use case: Useful for building iterators, managing async flows before async/await
.
✅ 6. Async Functions (async/await
)
Used to write asynchronous code in a synchronous style. Always returns a Promise.
Example
async function fetchData() {
return "Data fetched";
}
fetchData().then(result => console.log(result)); // Output: Data fetched
async function fetchData() {
return "Data fetched";
}
fetchData().then(result => console.log(result)); // Output: Data fetched
With await
:
function getData() {
return new Promise(resolve => {
setTimeout(() => resolve("Data loaded"), 1000);
});
}
async function load() {
const data = await getData();
console.log(data); // Output (after 1s): Data loaded
}
load();
function getData() {
return new Promise(resolve => {
setTimeout(() => resolve("Data loaded"), 1000);
});
}
async function load() {
const data = await getData();
console.log(data); // Output (after 1s): Data loaded
}
load();
Function Concepts
-
First-Class Functions
-
Higher-Order Functions
-
Callback Functions
-
Pure vs Impure Functions
-
Recursive Functions
-
Closures in JavaScript
✅ 1.First-Class Functions
In JavaScript, functions are first-class citizens. This means functions can:
-
Be assigned to variables,
-
Be passed as arguments to other functions,
-
Be returned from other functions.
✅ Example:
// Assigned to a variableconst greet = function(name) { return `Hello, ${name}`;};
// Passed as an argumentfunction processGreeting(fn, name) { console.log(fn(name));}
processGreeting(greet, "Alice"); // Output: Hello, Alice
// Returned from another functionfunction multiplier(factor) { return function(num) { return num * factor; };}
const double = multiplier(2);console.log(double(5)); // Output: 10
✅ 2.Higher-Order Functions
A higher-order function is a function that either takes another function as an argument, returns a function, or both.
In other words: Every higher-order function uses first-class functions, but not all first-class functions are higher-order.
✅ Example:
function multiply(factor) { return function(num) { return num * factor; };}
const double = multiply(2);console.log(double(5)); // Output: 10
Key Points:
-
Used in array methods (
map
,filter
,reduce
) -
Promotes cleaner and modular code
3. ✅ Callback Functions
🔸 Explanation:
A callback function is passed into another function as an argument and executed later.
✅ Example:
function fetchData(callback) { setTimeout(() => { callback("Data received"); }, 1000);}
fetchData(function(data) { console.log(data); // Output: Data received});
🔑 Key Points:
-
Used heavily in async programming
-
Can cause "callback hell" if nested deeply (solved with Promises/async-await)
4. ✅ Pure vs Impure Functions
🔸 Pure Function:
-
No side effects
-
Given same inputs, always returns same output
✅ Example:
function add(a, b) { return a + b;}
🔸 Impure Function:
-
Has side effects (e.g., modifying global variables, DOM, I/O)
-
May return different outputs for same inputs
✅ Example:
let count = 0;function increment() { count++; return count;}
🔑 Key Points:
-
Pure functions are predictable and testable
-
Impure functions are common in real-world apps (logging, user input)
5. ✅ Recursive Functions
🔸 Explanation:
A recursive function calls itself until it reaches a base condition.
✅ Example: Factorial
function factorial(n) { if (n === 1) return 1; return n * factorial(n - 1);}
console.log(factorial(5)); // Output: 120
🔑 Key Points:
-
Always define a base case to avoid infinite loop
-
Useful for tree structures, nested loops
6. ✅ Closures in JavaScript
🔸 Explanation:
A closure is when a function remembers variables from its lexical scope even after the outer function has finished executing.
✅ Example:
function outer() { let count = 0; return function inner() { count++; console.log(count); };}
const counter = outer();counter(); // Output: 1counter(); // Output: 2
🔑 Key Points:
- Inner function "closes over" outer variables
- Used for data privacy and maintaining state
- Common in functional patterns and event handlers
Advanced Function Features
-
Rest Parameters (
...args
) -
Spread Operator in Function Calls
-
Function Overloading in JS (workarounds)
-
Currying Functions
-
Memoization
✅ 1. Rest Parameters (...args
)
🔸 Explanation:
Rest parameters allow a function to accept multiple arguments as an array.✅ Example:
function sum(...numbers) { return numbers.reduce((total, num) => total + num, 0);}
console.log(sum(1, 2, 3, 4)); // Output: 10
🔑 Key Points:
- Gathers remaining arguments into an array
- Can only be the last parameter
- Useful when number of arguments is unknown
✅ 2. Spread Operator in Function Calls
🔸 Explanation:
The spread operator (...
) expands an array into individual elements.
✅ Example:
const nums = [1, 2, 3];console.log(Math.max(...nums)); // Output: 3
🔑
Key Points:
- Opposite of rest parameters
- Useful for passing arrays into functions or combining arrays
✅ 3. Function Overloading in JS (Workarounds)
🔸 Explanation:
JavaScript doesn't support traditional function overloading, but you can simulate it using conditions inside the function.
✅ Example:
function greet(name, age) { if (age !== undefined) { return `Hello, ${name}. You are ${age} years old.`; } else { return `Hello, ${name}.`; }}
console.log(greet("Alice")); // Hello, Alice.console.log(greet("Alice", 25)); // Hello, Alice. You are 25 years old.
🔑 Key Points:
-
Check the number or type of arguments using arguments.length
or typeof
-
Simulates overloading behavior
Check the number or type of arguments using arguments.length
or typeof
Simulates overloading behavior
✅4. Currying Functions
🔸 Explanation:
Currying is transforming a function with multiple arguments into a series of functions each taking one argument.
✅ Example:
function multiply(a) { return function(b) { return a * b; };}
const double = multiply(2);console.log(double(5)); // Output: 10
🔑 Key Points:
- Useful for creating reusable functions
- Helps in function composition and partial application
✅ 5. Memoization
🔸 Explanation:
Memoization is a performance optimization that caches function results to avoid recalculating for the same inputs.
✅ Example:
function memoize(fn) { const cache = {}; return function(arg) { if (cache[arg]) { console.log("From cache"); return cache[arg]; } else { const result = fn(arg); cache[arg] = result; return result; } };}
const square = memoize(x => x * x);console.log(square(4)); // Output: 16console.log(square(4)); // Output: 16 (From cache)
🔑 Key Points:
- Improves performance for expensive computations
- Best for pure functions
Scope & Context
- Function Scope vs Block Scope
- Lexical Scope
- this keyword inside functions
- Binding this (call, apply, bind)
- Arrow Functions and this
✅ 1. Function Scope vs Block Scope
🔸 Function Scope:
Variables declared with var
are scoped to the function in which they are declared.
✅ Example:
function testVar() { if (true) { var x = 10; } console.log(x); // Output: 10 (accessible outside the block)}
🔸 Block Scope:
Variables declared with let
or const
are scoped to the block {}
in which they are defined.
✅ Example:
function testLet() { if (true) { let y = 20; } console.log(y); // ❌ Error: y is not defined}
🔑 Key Points:
-
Use let
and const
to avoid scope issues.
-
var
leaks outside block—avoid using it unless needed.
Use let
and const
to avoid scope issues.
var
leaks outside block—avoid using it unless needed.
✅ 2. Lexical Scope
🔸 Explanation:
Lexical scope means that inner functions have access to variables from their outer (parent) function scope.
✅ Example:
function outer() { const outerVar = "I'm outside!"; function inner() { console.log(outerVar); // ✅ Accesses outerVar }
inner();}
outer();
🔑 Key Points:
-
Determined at write-time, not runtime.
-
Enables closures.
-
Scope chain moves outward, not inward.
Determined at write-time, not runtime.
Enables closures.
Scope chain moves outward, not inward.
✅ 3. this
Keyword Inside Functions
🔸 Explanation:
this
refers to the object that is calling the function, but its behavior differs by context.
🔹 Global Context:
console.log(this); // In browser: refers to `window` object
🔹 Inside a regular function:
function showThis() { console.log(this);}
showThis(); // In strict mode: undefined, otherwise window
🔹 Inside an object method:
const user = { name: "Alice", greet() { console.log(this.name); }};
user.greet(); // Output: Alice
🔑 Key Points:
-
In non-strict mode, this
in global scope refers to window
.
-
In object methods, this
refers to the object itself.
-
In standalone functions, this
may be undefined
in strict mode.
In non-strict mode, this
in global scope refers to window
.
In object methods, this
refers to the object itself.
In standalone functions, this
may be undefined
in strict mode.
✅ 4. Binding this
(call, apply, bind)
🔸 call()
– Calls the function with a given this
and args (comma-separated)
function greet(greeting) { console.log(`${greeting}, ${this.name}`);}
const person = { name: "John" };greet.call(person, "Hello"); // Output: Hello, John
🔸 apply()
– Same as call
but arguments are passed as an array
greet.apply(person, ["Hi"]); // Output: Hi, John
🔸 bind()
– Returns a new function with bound this
const sayHi = greet.bind(person, "Hey");sayHi(); // Output: Hey, John
🔑 Key Points:
-
call
and apply
immediately invoke the function.
-
bind
returns a new function without invoking it.
-
Used for explicit control over this
.
call
and apply
immediately invoke the function.
bind
returns a new function without invoking it.
Used for explicit control over this
.
✅ 5. Arrow Functions and this
🔸 Explanation:
Arrow functions don’t have their own this
. They inherit it from the lexical (outer) scope.
✅ Example:
const person = { name: "Alice", greet: function () { const arrow = () => { console.log(this.name); // Refers to person }; arrow(); }};
person.greet(); // Output: Alice
🔹 Compare with regular function:
const person = { name: "Alice", greet: function () { function regular() { console.log(this.name); // ❌ undefined (this is window/global) } regular(); }};
person.greet(); // Output: undefined
🔑 Key Points:
-
Arrow functions do not bind their own this
.
-
Use arrow functions in callbacks where you want to preserve outer this
.
Arrow functions do not bind their own this
.
Use arrow functions in callbacks where you want to preserve outer this
.
📌 Summary Table
Function Execution
-
Execution Context & Call Stack
-
Hoisting in Functions
-
Event Loop and Function Calls
-
Synchronous vs Asynchronous Execution
Execution Context & Call Stack
Hoisting in Functions
Event Loop and Function Calls
Synchronous vs Asynchronous Execution
✅ 1. Execution Context & Call Stack
🔸 Execution Context:
An execution context is the environment in which JavaScript code is evaluated and executed.
There are three main types:
-
Global Execution Context (GEC): Created when the script first runs.
-
Function Execution Context (FEC): Created whenever a function is invoked.
-
Eval Execution Context: Rarely used (from
eval()
).
✅ Example:
var x = 10;
function outer() { var y = 20; function inner() { var z = 30; console.log(x + y + z); } inner();}
outer(); // Output: 60
🧠 Behind the scenes:
-
Global Execution Context runs first
-
Then, outer function’s context is pushed to call stack
-
Then, inner function’s context is pushed
🔑 Key Points:
-
JavaScript runs in a single thread
-
Each function call creates a new execution context
-
Contexts are managed using a Call Stack
JavaScript runs in a single thread
Each function call creates a new execution context
Contexts are managed using a Call Stack
✅ 2. Hoisting in Functions
🔸 Explanation:
Hoisting means that function declarations and variables (var
) are moved to the top of their scope before code execution.
✅ Example:
greet(); // Output: Hello
function greet() { console.log("Hello");}
✅ Works because greet()
is hoisted.
❌ But for function expressions:
sayHi(); // ❌ TypeError: sayHi is not a function
var sayHi = function () { console.log("Hi");};
🔑 Key Points:
-
Function declarations are fully hoisted.
-
Function expressions are hoisted as
undefined
. -
Always declare functions at the top for clarity.
✅ 3. Event Loop and Function Calls
🔸 Explanation:
The event loop handles asynchronous callbacks in the browser or Node.js.
✅ Example:
console.log("Start");
setTimeout(() => { console.log("Timeout");}, 0);
console.log("End");
✅ Output:
StartEndTimeout
📌 Why?
-
setTimeout()
is asynchronous. -
It goes to Web APIs, and its callback is queued in the Callback Queue.
-
The event loop pushes it to the Call Stack only when it's empty.
🔑 Key Points:
-
JavaScript uses a single-threaded, non-blocking event loop.
-
Asynchronous functions (e.g.,
setTimeout
,fetch
) are queued and processed after the current call stack is clear.
✅ 4. Synchronous vs Asynchronous Execution
🔸 Synchronous:
Code is executed line by line, blocking further execution until the current line finishes.
✅ Example:
console.log("1");console.log("2");console.log("3");
✅ Output:
123
🔸 Asynchronous:
Code does not wait and allows the next lines to run immediately.
✅ Example:
console.log("1");
setTimeout(() => { console.log("2");}, 1000);
console.log("3");
✅ Output:
123
🔑 Key Points:
📌 Summary Table
Built-in Function Methods
-
setTimeout
and setInterval
-
Function.prototype.bind()
-
Function.prototype.call()
-
Function.prototype.apply()
-
toString()
, name
, length
properties of functions
setTimeout
and setInterval
Function.prototype.bind()
Function.prototype.call()
Function.prototype.apply()
toString()
, name
, length
properties of functions
✅ 1. setTimeout()
and setInterval()
🔸 setTimeout(fn, delay)
Executes a function once after a delay (in milliseconds).
✅ Example:
setTimeout(() => { console.log("Executed after 2 seconds");}, 2000);
🔸 setInterval(fn, delay)
Executes a function repeatedly at a given interval.
✅ Example:
let count = 0;const interval = setInterval(() => { console.log("Interval running", ++count); if (count === 3) clearInterval(interval);}, 1000);
🔑 Key Points:
- Asynchronous functions.
- Use clearTimeout() and clearInterval() to stop them.
✅ 2. Function.prototype.bind()
🔸 Explanation:
Returns a new function with this permanently bound to the provided object.
Example:
const person = { name: "Alice" };
function greet() { console.log("Hello " + this.name);}
const boundGreet = greet.bind(person);boundGreet(); // Output: Hello Alice
🔑 Key Points:
- Doesn’t invoke the function immediately.
- Creates a copy of the function with bound this.
✅3. Function.prototype.call()
🔸 Explanation:
Calls a function with a specified this value and arguments passed individually.
Example:
function say(greeting, punctuation) { console.log(`${greeting}, ${this.name}${punctuation}`);}
const user = { name: "Bob" };say.call(user, "Hi", "!"); // Output: Hi, Bob!
🔑 Key Points:
- Invokes the function immediately.
- Arguments are passed one-by-one.
✅4. Function.prototype.apply()
🔸 Explanation:
Same as call(), but arguments are passed as an array.
Example:
say.apply(user, ["Hello", "."]); // Output: Hello, Bob.
🔑 Key Points:
- Useful when you already have arguments in an array or want to spread them.
✅ 5. Function Properties
🔸 toString()
Returns the source code of the function as a string.
Example:
function test() { return "hello";}
console.log(test.toString());// Output: function test() { return "hello"; }
🔸 name
Returns the name of the function.
Example:
console.log(test.name); // Output: test
🔸 length
Returns the number of expected parameters (not including rest parameters).