Last 30 Days
No notifications
JavaScript is the programming language of the browser (and beyond, via Node.js). Mastering variables, types, operators, control flow, functions, and scope is the foundation for everything.
| Keyword | Scope | Reassignable | Hoisted | ||||
var | Function | ✅ | ✅ (as undefined) | ||||
let | Block | ✅ | ❌ (TDZ) | ||||
const | Block | ❌ | ❌ (TDZ) | Rule: Default to Data Types | Primitive | Example | typeof |
| String | "hello" | "string" | |||||
| Number | 42, 3.14 | "number" | |||||
| Boolean | true | "boolean" | |||||
| undefined | undefined | "undefined" | |||||
| null | null | "object" (bug) | |||||
| BigInt | 9007199254740993n | "bigint" | |||||
| Symbol | Symbol("id") | "symbol" |
Non-primitives: Object, Array, Function (all reference types).
// Always use strict equality
5 === 5 // true (same type + value)
5 == "5" // true (coerces type — avoid!)
5 === "5" // false (different types)if (condition) { … }
else if (other) { … }
else { … }for (let i = 0; i < arr.length; i++) { … }
for (const item of arr) { … } // iterate values
for (const key in obj) { … } // iterate keys
while (condition) { … }
switch (value) { case 'a': …; break; }
Functions are first-class — they can be assigned to variables, passed as arguments, and returned from other functions. Each function creates its own scope.
HTML is the *structure* of a page, CSS is the *look*. JavaScript is the behaviour — the language that makes a button do something when you click it, fetches data from a server, or animates an element. It's the only programming language that runs natively in every browser.
If you can read a recipe, you can read JavaScript: it's a list of instructions the browser executes top to bottom.
Open any web page, press F12, click Console, and type:
console.log("Hello, world!");That's it — you're a JavaScript developer. console.log prints a value into that console panel. You'll use it constantly while debugging.
let age = 21; // can change later
const name = "Asha"; // cannot change| Keyword | Reassignable? | Use it for | |||
const | No | Almost everything (default) | |||
let | Yes | Counters, accumulators, anything you'll reassign | |||
var | Yes | Avoid — old, function-scoped, surprising | Rule of thumb: start with Data Types in 30 Seconds | Type | Example |
| String | "hello" or 'hi' or \bye\`` | ||||
| Number | 42, 3.14 (no separate int/float) | ||||
| Boolean | true, false | ||||
| null | null (intentional empty) | ||||
| undefined | undefined (variable declared but no value) | ||||
| Object | { name: "Asha", age: 21 } | ||||
| Array | [1, 2, 3] (an object too, technically) |
Use typeof value to check at runtime.
Old way: "Hello, " + name + "!"
New way (backticks):
const greeting = Hello, ${name}! You are ${age}.;Backticks also support multi-line strings without \n.
// Arithmetic
1 + 2; 5 * 3; 10 / 4; 10 % 3; // remainder = 1
2 ** 10; // exponent = 1024// Comparison — ALWAYS prefer === over ==
5 === "5"; // false (strict, types matter)
5 == "5"; // true (loose, coerces — avoid)
// Logical
true && false; // and
true || false; // or
!true; // not
if (age >= 18) {
console.log("adult");
} else if (age >= 13) {
console.log("teen");
} else {
console.log("kid");
}// Ternary — a one-line if/else
const label = age >= 18 ? "adult" : "minor";
// Loops
for (let i = 0; i < 5; i++) console.log(i);
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) console.log(fruit);
Three ways to define a function — pick whichever feels natural at first:
// 1. Function declaration
function add(a, b) { return a + b; }// 2. Function expression
const subtract = function (a, b) { return a - b; };
// 3. Arrow function (modern, concise)
const multiply = (a, b) => a * b;
const square = n => n * n; // single param, no parens
const greet = name => {
console.log(Hi, ${name});
};
Arrow functions are the most common in modern code. Use function declarations when you want hoisting (more on that below).
const nums = [10, 20, 30];nums.length; // 3
nums[0]; // 10
nums.push(40); // add to end
nums.pop(); // remove last
nums.includes(20); // true
// Modern iteration — learn these three before everything else:
nums.map(n => n * 2); // [20, 40, 60]
nums.filter(n => n > 15); // [20, 30]
nums.reduce((sum, n) => sum + n, 0); // 60
const user = { name: "Asha", age: 21, email: "a@x.com" };user.name; // "Asha"
user["age"]; // 21
user.role = "admin"; // add a property
// Destructuring — pull fields out cleanly
const { name, age } = user;
// Spread — copy + extend
const updated = { ...user, age: 22 };
1. Using == instead of === — gives wrong answers like 0 == "" → true.
2. Forgetting return in a function — it silently returns undefined.
3. Mutating a const object — const user = {} only locks the *binding*; you can still change properties. Use Object.freeze if you really need immutability.
4. Looping with for...in over arrays — iterates indices and inherited keys. Use for...of or .forEach instead.
5. Re-declaring with var inside a block and being shocked it leaks out.
JavaScript uses lexical (static) scope — a function can access variables from its enclosing scope based on where it's *written*, not where it's called.
function outer() {
const x = 10;
function inner() {
console.log(x); // 10 — sees outer's x
}
inner();
}let and const are block-scoped (live only inside the nearest { }); var is function-scoped (leaks out of blocks). One more reason to skip var.
A closure is a function that remembers the variables of the scope where it was created — even after that scope has ended.
function makeCounter() {
let count = 0;
return () => ++count;
}const counter = makeCounter();
counter(); // 1
counter(); // 2 — count is alive inside the closure
Closures power every callback, event handler, and module pattern in JavaScript. They also enable data privacy:
function makeWallet(initial) {
let balance = initial; // private — no outside access
return {
deposit: (n) => { balance += n; },
getBalance: () => balance,
};
}JavaScript "hoists" declarations to the top of their scope before running the code:
| Declaration | Hoisted? | Initialised? |
function declaration | Yes | Yes (full body) |
var | Yes | As undefined |
let / const | Yes | No — touching them throws ReferenceError (the *Temporal Dead Zone*) |
| Arrow functions / function expressions | No | — |
console.log(x); // undefined (hoisted var)
console.log(y); // ReferenceError (TDZ)
var x = 1;
let y = 2;JavaScript will silently convert types around you:
"5" + 3 // "53" — + with a string = concat
"5" - 3 // 2 — - forces numeric
null + 1 // 1
undefined + 1 // NaN
[] + [] // ""
[] + {} // "[object Object]"Defence: always use ===, and convert explicitly with Number(x), String(x), Boolean(x).
this Without the HeadacheIn a regular function, this depends on how it's called:
function show() { console.log(this); }
show(); // window / undefined (strict)
const obj = { show };
obj.show(); // obj — called as a methodIn an arrow function, this is whatever this was in the *surrounding* code — it never has its own. That's exactly why arrows are perfect for callbacks inside class methods.
JavaScript runs on a single thread but feels async because of the event loop:
Call Stack ──────► runs sync code
│
│ schedules async work
▼
Web APIs (timers, fetch, DOM events)
│ when ready
▼
Microtask queue (promises) ── higher priority
Macrotask queue (setTimeout, etc.)
│
▼ event loop pops one task when stack is emptyWhy does Promise.resolve().then(…) always run before setTimeout(…, 0)? Microtasks drain *before* the next macrotask. Knowing this saves hours of head-scratching.
Modern JavaScript splits code across files using import/export:
// math.js
export const PI = 3.14;
export function add(a, b) { return a + b; }// app.js
import { PI, add } from "./math.js";
In the browser, add . In Node, set "type": "module" in package.json.
1. Open the console and rewrite a small for-loop using map, filter, and reduce.
2. Build a closure-based counter with increment, decrement, and get methods — no class allowed.
3. Predict the output of mixed setTimeout + Promise.then snippets, *then* run them.
4. Convert a file of var + function code to const + arrow functions; fix anything that breaks.