Blog Summary: The bedrock of the course. Covers why JS exists, how it runs, and the async programming model that makes JS unique and powerful for web development.
1. Why Programming Languages?
[SOURCE — COURSE MATERIAL]
Computers understand only binary (0s and 1s). Languages exist so humans can write readable instructions that compilers/interpreters then convert to binary.
Human-written code → Compiler → 01010101 → CPU executes
The flow:
- Developer writes high-level code (JS, Python, C++)
- A compiler/runtime converts it to machine code
- CPU executes machine code from RAM
- SSD holds the program at rest; RAM holds it while running
2. Compiled vs Interpreted (Scripting) Languages
[SOURCE — COURSE MATERIAL]
| Type | Compiled | Interpreted / Scripting |
|---|---|---|
| Examples | C, C++, Go, Rust | JavaScript, Python |
| Execution | Must compile first, then run | Runs line by line at runtime |
| Speed | Faster at runtime | Slower but flexible |
| Dev cycle | Compile → Run | Just run |
C++ compile flow:
# Step 1: Write code
# Step 2: Compile
g++ main.cpp -o main
# Step 3: Run
./main
JavaScript — no compile step needed:
node index.js # Just run it
[ADDED — EXPLANATION] JS was originally a scripting language for browsers. The JS engine (V8 in Chrome) compiles JS to machine code just-in-time (JIT) at runtime. This is why JS can be fast even though it’s “interpreted.”
3. Why JavaScript Over Other Languages?
[SOURCE — COURSE MATERIAL]
JS dominates web because:
- It’s the only language browsers understand natively
- Works on frontend AND backend (Node.js)
- Huge ecosystem (npm)
- Async model is perfect for I/O-heavy web servers
[ADDED — IMPORTANT BACKGROUND] JS was not designed to be a backend language. It was created in 1995 by Brendan Eich for Netscape to make web pages interactive. Node.js (2009) changed everything — someone took the V8 engine out of Chrome and added file system/network APIs on top, making JS capable on the backend.
4. Static vs Dynamic Typing
[SOURCE — COURSE MATERIAL]
// Dynamic (JS) — types are inferred at runtime
let x = 5; // number
x = "hello"; // now a string — totally fine
// Static (TypeScript / Java) — type declared, enforced
let x: number = 5;
x = "hello"; // ERROR at compile time
Implication: JS is flexible but error-prone. TypeScript adds types on top (covered later).
5. Single-Threaded Nature of JS
[SOURCE — COURSE MATERIAL]
JS has one call stack — it can only do one thing at a time.
Mental model: Your brain is single-threaded — it can truly focus on only one task. But you delegate background tasks (boiling water, washing machine running) and context-switch between quick tasks.
JS does the same:
- Delegate long operations (file reads, network) to the browser/OS
- Context switch using the event loop
JS Thread: executes code → hits async call → delegates → continues → callback fires later
6. JavaScript Primitives
[SOURCE — COURSE MATERIAL]
Simple Primitives:
// Number
let age = 25;
let price = 9.99;
// String
let name = "Harkirat";
let greeting = `Hello, ${name}!`; // template literal
// Boolean
let isLoggedIn = true;
let hasPaid = false;
// Null / Undefined
let nothing = null; // explicitly nothing
let unknown; // undefined — declared but no value
Complex Primitives (Reference Types):
// Array
let fruits = ["apple", "banana", "cherry"];
fruits[0]; // "apple"
fruits.push("mango"); // adds to end
fruits.length; // 4
// Object
let user = {
name: "Harkirat",
age: 25,
isAdmin: false,
};
user.name; // "Harkirat"
user["age"]; // 25 — bracket notation
7. Functions
[SOURCE — COURSE MATERIAL]
A function takes input, does something, returns output.
// Function declaration
function add(a, b) {
return a + b;
}
// Function expression (stored in variable)
const multiply = function (a, b) {
return a * b;
};
// Arrow function (modern, concise)
const square = (n) => n * n;
// Calling
add(3, 4); // 7
square(5); // 25
Why functions? DRY principle (Don’t Repeat Yourself):
// BAD — repeated logic
console.log(1 * 1);
console.log(2 * 2);
console.log(3 * 3);
// GOOD — reusable function
function printSquare(n) {
console.log(n * n);
}
printSquare(1);
printSquare(2);
printSquare(3);
8. Loops
[SOURCE — COURSE MATERIAL]
// For loop — sum from 1 to 100
let sum = 0;
for (let i = 1; i <= 100; i++) {
sum += i;
}
console.log(sum); // 5050
// While loop
let count = 0;
while (count < 5) {
console.log(count);
count++;
}
// Array iteration
const nums = [1, 2, 3, 4, 5];
for (let i = 0; i < nums.length; i++) {
console.log(nums[i]);
}
// Modern style:
nums.forEach((n) => console.log(n));
9. Callback Functions
[SOURCE — COURSE MATERIAL]
A callback is a function passed as an argument to another function, to be called later.
// Basic callback concept
function doMath(a, b, operation) {
return operation(a, b);
}
function add(x, y) {
return x + y;
}
function multiply(x, y) {
return x * y;
}
doMath(3, 4, add); // 7
doMath(3, 4, multiply); // 12
// Anonymous callback (no separate function)
doMath(3, 4, function (x, y) {
return x - y;
}); // -1
doMath(3, 4, (x, y) => x ** y); // 81 (arrow function)
[ADDED — EXPLANATION] Callbacks are the foundation of async programming in JS. When you say “call this function when you’re done,” that’s a callback.
10. Asynchronous Programming
[SOURCE — COURSE MATERIAL]
Problem: Synchronous blocking
// Everything stops while waiting
const data = readFile("large-file.txt"); // blocks for 5 seconds
console.log("This prints after 5 seconds"); // bad!
Async solution — delegate and continue:
// setTimeout — basic async function
console.log("1: Start");
setTimeout(function () {
console.log("3: Callback fires after 1 second");
}, 1000);
console.log("2: This runs immediately");
// Output:
// 1: Start
// 2: This runs immediately
// 3: Callback fires after 1 second
Real async functions:
const fs = require("fs");
// Non-blocking file read
fs.readFile("data.txt", "utf8", function (error, content) {
if (error) {
console.log("Error reading file:", error);
return;
}
console.log("File contents:", content);
});
console.log("This runs before file is read!"); // prints first
11. The Event Loop
[SOURCE — COURSE MATERIAL]
[ADDED — IMPORTANT BACKGROUND] The event loop is JavaScript’s mechanism for handling async operations despite being single-threaded.
Call Stack Web APIs/OS Callback Queue
───────── ────────── ──────────────
main() ──→ setTimeout (1s timer)
fs.readFile
fetch
When complete: callback is pushed to Callback Queue
Event loop checks: if Call Stack is empty, push from Queue → Stack
Visualization: http://latentflip.com/loupe — highly recommended
Key rule: A callback only executes when the call stack is completely empty.
12. Callback Hell
[SOURCE — COURSE MATERIAL]
// The "Pyramid of Doom" — deeply nested callbacks
setTimeout(function () {
console.log("After 1 second");
setTimeout(function () {
console.log("After 2 more seconds");
setTimeout(function () {
console.log("After 3 more seconds");
// imagine 10 more levels...
}, 3000);
}, 2000);
}, 1000);
13. Promises
[SOURCE — COURSE MATERIAL]
Promises are syntactic sugar over callbacks. They make async code readable.
// Creating a Promise
function wait(ms) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("Done waiting!");
}, ms);
});
}
// Using .then() chaining — NO nesting!
wait(1000)
.then(function (result) {
console.log(result); // "Done waiting!"
return wait(2000);
})
.then(function (result) {
console.log("Two more seconds passed");
})
.catch(function (error) {
console.log("Something went wrong:", error);
});
Promise states:
pending— initial, waitingfulfilled— resolved successfullyrejected— failed
14. Async/Await
[SOURCE — COURSE MATERIAL]
Async/await is syntactic sugar over Promises. Reads like synchronous code.
// Same logic as above, much cleaner
async function main() {
try {
const result = await wait(1000);
console.log(result); // "Done waiting!"
await wait(2000);
console.log("Two more seconds passed");
} catch (error) {
console.log("Error:", error);
}
}
main();
Rules:
asynckeyword makes a function return a Promiseawaitpauses execution until Promise resolves (only insideasyncfunctions)- Always wrap in
try/catch
15. Array Methods: map & filter
[SOURCE — COURSE MATERIAL]
const numbers = [1, 2, 3, 4, 5, 6];
// map — transform each element
const doubled = numbers.map((n) => n * 2);
// [2, 4, 6, 8, 10, 12]
// filter — keep elements that pass a test
const evens = numbers.filter((n) => n % 2 === 0);
// [2, 4, 6]
// Chain them
const doubledEvens = numbers.filter((n) => n % 2 === 0).map((n) => n * 2);
// [4, 8, 12]
Exercises
Quick (10–15 min)
Write a function sumArray(arr) that returns the sum of all elements using a for loop. Then rewrite it using reduce.
Hint 1: reduce takes a callback and an initial value.
Hint 2: arr.reduce((acc, curr) => acc + curr, 0)
Common mistakes: Forgetting the initial value 0 in reduce.
Intermediate (30–60 min)
Create a function fetchAndLog(url) that:
- Fetches data from a URL (use Node’s
httpsmodule or browserfetch) - Logs the result after 2 seconds (use
setTimeout) - Handles errors gracefully
Expected behavior: Data prints after delay. If URL is bad, logs an error.
Hint 1: Chain .then() before setTimeout, or use await.
Hint 2: Wrap in async/await with try/catch.
Challenge (1–2 hours)
Implement your own Promise class from scratch (simplified):
- Constructor takes an executor function with
resolveandreject .then()method registers success handler.catch()registers error handler
Common Confusions
| Confusion | Reality |
|---|---|
| “Async means parallel” | No. JS is still single-threaded. Async means non-blocking delegation. |
“await pauses JS entirely” |
No. It pauses the current async function only. Other code can run. |
| “Promises and callbacks are different things” | Promises are built ON callbacks. They’re just cleaner syntax. |
| “Arrow functions are just shorter syntax” | They also don’t have their own this — important for OOP. |
Key Takeaways
- JS is single-threaded, interpreted, dynamically typed
- Async programming is the core superpower of JS — delegation + event loop
- Callbacks → Promises → Async/Await: each solves readability of the last
mapandfilterare functional programming tools — prefer them over manual loops for transformations