JavaScript

1. What is JavaScript?

JavaScript is a lightweight, interpreted, dynamically-typed scripting language that runs inside web browsers (and on servers via Node.js). It makes web pages interactive — responding to clicks, validating forms, updating content without page reloads.

FeatureJavaScriptJava
TypeScripting languageObject-oriented programming language
TypingDynamic (types checked at runtime)Static (types checked at compile time)
Compiled?Interpreted (by browser/Node.js)Compiled to bytecode, run on JVM
Where it runsBrowser + Node.jsJVM (any platform)
Syntax styleC-like but loosely typedStrictly typed, verbose
RelationNone — the name is purely a marketing decision. They are completely different languages.
📋 Exam Fact
JavaScript was created by Brendan Eich in 1995 at Netscape. The official standard is called ECMAScript (ES). ES6 (2015) introduced major features: let, const, arrow functions, classes, template literals.

2. Data Types & typeof

JavaScript has 7 primitive types and 1 structural type:

TypeExampletypeof result
string"hello", 'world'"string"
number42, 3.14, NaN, Infinity"number"
booleantrue, false"boolean"
undefinedundefined (variable declared, not assigned)"undefined"
nullnull (intentional empty value)"object" ⚠️ (historic bug)
symbolSymbol("id")"symbol"
bigint9007199254740991n"bigint"
object{}, [], null"object"
functionfunction() {}"function"
typeof "hello"       // "string"
typeof 42            // "number"
typeof true          // "boolean"
typeof undefined     // "undefined"
typeof null          // "object"  ← famous JavaScript bug, memorise this!
typeof NaN           // "number"  ← NaN is technically a number type!
typeof []            // "object"  ← arrays are objects
typeof function(){}  // "function"
💡 Exam tip
typeof null === "object" and typeof NaN === "number" are the two most-tested typeof surprises. Memorise both.

3. var vs let vs const

Featurevarletconst
ScopeFunction scopeBlock scope {}Block scope {}
Hoisted?Yes — initialised as undefinedYes — but in TDZ (not usable)Yes — but in TDZ (not usable)
Re-declare same scope?✅ Yes❌ No❌ No
Reassign value?✅ Yes✅ Yes❌ No
Must initialise?NoNo✅ Yes
// var — function scoped
function test() {
  if (true) {
    var x = 10;
  }
  console.log(x); // 10 — var leaks out of the if block!
}

// let — block scoped
function test2() {
  if (true) {
    let y = 20;
  }
  console.log(y); // ReferenceError: y is not defined
}

// const — cannot reassign
const PI = 3.14;
PI = 3; // TypeError: Assignment to constant variable

// const with objects — the reference is fixed, but contents can change
const obj = { a: 1 };
obj.a = 99; // ✅ allowed — changing a property
obj = {};    // ❌ not allowed — reassigning the variable
⚠️ Warning — Hoisting Trap
var declarations are moved to the top of their function and set to undefined. let and const are hoisted but sit in the Temporal Dead Zone (TDZ) — accessing them before declaration throws a ReferenceError, not undefined.
// var hoisting — classic exam question
console.log(a); // undefined (hoisted, but not yet assigned)
var a = 5;
console.log(a); // 5

// let TDZ — throws error
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 5;

4. Operators

Arithmetic Operators

+   // addition (also string concatenation)
-   // subtraction
*   // multiplication
/   // division
%   // modulo (remainder): 10 % 3 → 1
**  // exponentiation: 2 ** 3 → 8
++  // increment: x++ (post), ++x (pre)
--  // decrement

let x = 5;
console.log(x++); // 5 — returns THEN increments
console.log(x);   // 6
console.log(++x); // 7 — increments THEN returns

Comparison: == vs ===

// == (loose equality) — converts types before comparing
1 == "1"    // true  — string "1" is converted to number 1
0 == false  // true  — false converts to 0
null == undefined // true

// === (strict equality) — NO type conversion
1 === "1"   // false — different types
0 === false // false — different types
null === undefined // false
💡 Exam tip
Always prefer === in real code. The exam tests == heavily because its type coercion produces surprising results. When in doubt: == converts types, === does not.

Logical & Ternary Operators

// Logical
true && false  // false (AND — both must be true)
true || false  // true  (OR  — one must be true)
!true          // false (NOT)

// Ternary — shorthand if/else
// condition ? valueIfTrue : valueIfFalse
let age = 18;
let status = age >= 18 ? "adult" : "minor";
console.log(status); // "adult"

5. Type Coercion — The #1 Tricky Topic

JavaScript automatically converts values from one type to another. This is called implicit type coercion and it causes many surprising results.

🔑 Key Rule
The + operator: if either operand is a string, it concatenates. All other arithmetic operators (-, *, /, %) convert strings to numbers first.
// + with strings = concatenation
"1" + 2        // "12"  — number 2 becomes string "2"
1 + "2"        // "12"  — same result
"5" + 3 + 2   // "532" — left to right: "5"+3="53", "53"+2="532"
5 + 3 + "2"   // "82"  — 5+3=8 first (numbers), then 8+"2"="82"

// - * / always convert to number
"5" - 3        // 2   — "5" becomes number 5
"6" * "2"      // 12  — both become numbers
"10" / "2"    // 5
"abc" - 1     // NaN — "abc" can't be a number

// Boolean coercion
true + 1       // 2  — true becomes 1
false + 1      // 1  — false becomes 0
true + true    // 2

// null and undefined
null + 1       // 1  — null becomes 0
undefined + 1  // NaN

// Floating point trap
0.1 + 0.2       // 0.30000000000000004 — NOT 0.3!
0.1 + 0.2 == 0.3 // false — floating point precision issue
📋 Exam Pattern
Output prediction questions on type coercion appear in nearly every JS exam. Memorise: "1" + 2 = "12" and "5" - 3 = 2. The key: + concatenates strings, everything else forces numeric conversion.

6. Functions

// 1. Function Declaration — hoisted, can be called before it's written
function greet(name) {
  return "Hello, " + name;
}
console.log(greet("Darshan")); // "Hello, Darshan"

// 2. Function Expression — NOT hoisted
const add = function(a, b) {
  return a + b;
};
console.log(add(3, 4)); // 7

// 3. Arrow Function (ES6) — shorter syntax
const multiply = (a, b) => a * b;
console.log(multiply(3, 4)); // 12

// Arrow with body block (multiple statements)
const square = (n) => {
  let result = n * n;
  return result;
};

// Default parameters
function say(msg = "Hi") {
  console.log(msg);
}
say();        // "Hi"
say("Hello"); // "Hello"
💡 Exam tip
Arrow functions do not have their own this. They inherit this from the enclosing scope. Function declarations are hoisted — expressions are not.

7. Arrays & Array Methods

let arr = [1, 2, 3, 4, 5];

// Add / Remove
arr.push(6);        // adds to END   → [1,2,3,4,5,6]
arr.pop();          // removes END   → [1,2,3,4,5], returns 6
arr.unshift(0);    // adds to START → [0,1,2,3,4,5]
arr.shift();        // removes START → [1,2,3,4,5], returns 0

// splice(start, deleteCount, ...items) — modifies original
arr.splice(1, 2);      // removes 2 elements from index 1 → [1,4,5]
arr.splice(1, 0, 9);  // inserts 9 at index 1, deletes nothing

// slice(start, end) — returns new array, does NOT modify original
let part = [1,2,3,4,5].slice(1, 3); // [2, 3]  (index 1 up to but NOT including 3)

// Search
[10,20,30].indexOf(20);   // 1  (index of value 20)
[10,20,30].indexOf(99);   // -1 (not found)
[1,2,3].includes(2);       // true

// Iterate / Transform
[1,2,3].map(x => x * 2);      // [2, 4, 6]  — new array, every element transformed
[1,2,3,4].filter(x => x > 2); // [3, 4]    — new array, only matching elements
[1,2,3,4].reduce((acc, x) => acc + x, 0); // 10 — reduces to single value (sum here)
MethodMutates original?Returns
push()✅ YesNew length
pop()✅ YesRemoved element
shift()✅ YesRemoved element
unshift()✅ YesNew length
splice()✅ YesArray of removed elements
slice()❌ NoNew array (copy)
map()❌ NoNew array (transformed)
filter()❌ NoNew array (filtered)
reduce()❌ NoSingle accumulated value

8. String Methods

let s = "  Hello, World!  ";

s.length                 // 18 (including spaces)
s.trim()                 // "Hello, World!"  — removes leading/trailing whitespace
s.toUpperCase()          // "  HELLO, WORLD!  "
s.toLowerCase()          // "  hello, world!  "
s.indexOf("World")       // 9  (first occurrence index, -1 if not found)
s.includes("Hello")      // true
s.charAt(2)              // "H"  (character at index 2)
s.substring(2, 7)        // "Hello"  (from index 2 up to but not including 7)
s.replace("World", "JS") // "  Hello, JS!  "  (replaces first match)
s.split(",")             // ["  Hello", " World!  "]  — splits into array
"hello"[0]               // "h"  — strings are indexable

// Template literals (ES6) — backtick strings
let name = "Darshan";
let msg = `Hello, ${name}! You are ${20+1} years old.`;
// "Hello, Darshan! You are 21 years old."

9. Loops

// for loop
for (let i = 0; i < 3; i++) {
  console.log(i); // 0, 1, 2
}

// while loop
let i = 0;
while (i < 3) {
  console.log(i); // 0, 1, 2
  i++;
}

// do-while — runs at LEAST once even if condition is false
let j = 5;
do {
  console.log(j); // 5 — runs once even though 5 < 3 is false
} while (j < 3);

// for...in — iterates over KEYS of an object (or indexes of array)
const person = { name: "Ali", age: 25 };
for (let key in person) {
  console.log(key); // "name", "age"
}

// for...of — iterates over VALUES of iterable (array, string, etc.)
const nums = [10, 20, 30];
for (let val of nums) {
  console.log(val); // 10, 20, 30
}
🔑 Key Fact
for...in → keys/indexes. for...of → values. Use for...of for arrays, for...in for objects.

10. Objects

// Creating an object
const car = {
  brand: "Toyota",
  year: 2022,
  start: function() {
    return "Engine started!";
  }
};

// Accessing properties — dot notation
console.log(car.brand);    // "Toyota"
console.log(car.year);     // 2022

// Accessing properties — bracket notation (useful for dynamic keys)
console.log(car["brand"]); // "Toyota"
let prop = "year";
console.log(car[prop]);   // 2022

// Calling a method
console.log(car.start()); // "Engine started!"

// Adding / modifying properties
car.color = "red";  // adds new property
car.year = 2023;   // modifies existing

// Deleting a property
delete car.color;

11. DOM Manipulation

The DOM (Document Object Model) is the browser's representation of the HTML page as a tree of objects. JavaScript can read and change it.

// Selecting elements
document.getElementById("myBtn")         // by id — returns single element
document.querySelector(".myClass")       // CSS selector — returns FIRST match
document.querySelectorAll("p")           // CSS selector — returns ALL matches (NodeList)
document.getElementsByClassName("btn") // by class — returns HTMLCollection

// Changing content
let el = document.getElementById("title");
el.innerHTML = "<b>New Title</b>";  // sets HTML content
el.textContent = "Plain text";       // sets text only (safer — no HTML parsing)

// Changing styles
el.style.color = "red";
el.style.display = "none";

// Changing attributes
el.setAttribute("href", "https://example.com");
el.getAttribute("href");

// Adding event listener
el.addEventListener("click", function() {
  console.log("Clicked!");
});

12. Events

EventWhen it fires
onclickElement is clicked
onchangeValue of input/select changes
onsubmitForm is submitted
onloadPage or image finishes loading
onmouseoverMouse enters element
onkeydownKey is pressed down
onfocusInput element gets focus
onblurInput element loses focus
// Inline HTML (older style)
<button onclick="sayHi()">Click Me</button>

// addEventListener (preferred)
document.getElementById("btn").addEventListener("click", function(event) {
  event.preventDefault(); // stops default behavior (e.g., form submission)
  console.log("Button clicked");
});

13. Closures

A closure is when an inner function remembers variables from its outer function, even after the outer function has finished executing.

function makeCounter() {
  let count = 0;          // this variable lives in makeCounter's scope

  return function() {     // inner function — this is the closure
    count++;
    return count;
  };
}

const counter = makeCounter(); // makeCounter finished, but count survives
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

// Each call to makeCounter() creates a SEPARATE closure
const counter2 = makeCounter();
console.log(counter2()); // 1 — independent from counter
💡 Exam tip
Closures are used for data privacy — variables inside a closure can't be accessed from outside. The inner function "closes over" the outer variables.

14. The this Keyword

this refers to the object that is currently executing the function. Its value depends on how the function is called.

// In a method — this = the object
const person = {
  name: "Darshan",
  greet() {
    console.log(this.name); // "Darshan"
  }
};
person.greet();

// In a regular function (non-strict mode) — this = global (window)
function show() {
  console.log(this); // window (browser) or global (Node.js)
}

// Arrow functions — NO own this, inherits from enclosing scope
const obj = {
  name: "Test",
  regular: function() {
    console.log(this.name); // "Test" — this = obj
  },
  arrow: () => {
    console.log(this.name); // undefined — arrow uses outer this (window)
  }
};

15. Hoisting

🔑 Key Fact — Hoisting Summary
  • var declarations → hoisted to top of function, initialised as undefined
  • var assignments → NOT hoisted, stay where they are
  • function declarations → fully hoisted (name + body), callable anywhere
  • let / const → hoisted but in Temporal Dead Zone (TDZ) — throws ReferenceError if accessed before declaration
  • function expressions / arrow functions → follow the rules of the variable they're assigned to
// var hoisting
console.log(x); // undefined — declaration hoisted, assignment not
var x = 10;
console.log(x); // 10

// Function declaration hoisting — fully hoisted
sayHello(); // "Hello!" — works even before the function definition
function sayHello() { console.log("Hello!"); }

// let TDZ
console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 5;

// Function expression — NOT hoisted
greet(); // TypeError: greet is not a function
var greet = function() { console.log("Hi"); };

16. Truthy & Falsy Values

In JavaScript, every value is either truthy or falsy when evaluated in a boolean context (like an if statement).

⚠️ The 6 Falsy Values — Memorise These
false  |  0  |  "" (empty string)  |  null  |  undefined  |  NaN

Everything else is truthy — including "0", "false", [], {}.
// Falsy — all these if-blocks do NOT run
if (0)         { /* skipped */ }
if ("")        { /* skipped */ }
if (null)      { /* skipped */ }
if (undefined) { /* skipped */ }
if (NaN)       { /* skipped */ }

// Truthy — these DO run
if ("0")        { /* runs — non-empty string, even if "0" */ }
if ([])         { /* runs — empty array is truthy! */ }
if ({})         { /* runs — empty object is truthy! */ }
if ("false")    { /* runs — non-empty string is truthy */ }
if (-1)         { /* runs — any non-zero number is truthy */ }

17. NaN — Not a Number

typeof NaN         // "number" — NaN is paradoxically of type number
isNaN(NaN)        // true
isNaN("abc")      // true  — "abc" gets coerced to NaN
isNaN("123")      // false — "123" coerces to number 123
isNaN(undefined) // true  — undefined is NaN when converted

NaN === NaN       // false — NaN is NOT equal to itself!
NaN == NaN        // false — same rule

// How to properly check for NaN:
Number.isNaN(NaN)   // true  — stricter, doesn't coerce
Number.isNaN("abc") // false — "abc" is not NaN, it's a string
💡 Exam tip
NaN !== NaN is one of the most surprising facts in JavaScript. It is the only value in JS not equal to itself. Use isNaN() or Number.isNaN() to check for it.

18. JSON.parse() and JSON.stringify()

JSON (JavaScript Object Notation) is a text format for exchanging data. Two key methods convert between JSON strings and JS objects.

// JavaScript object → JSON string
const user = { name: "Darshan", age: 21 };
const json = JSON.stringify(user);
console.log(json);          // '{"name":"Darshan","age":21}'
console.log(typeof json); // "string"

// JSON string → JavaScript object
const str = '{"name":"Darshan","age":21}';
const obj = JSON.parse(str);
console.log(obj.name);      // "Darshan"
console.log(typeof obj);   // "object"

// JSON rules — keys must be double-quoted strings
// Invalid JSON: { name: "Darshan" }  — key must be "name"
// Valid JSON:   { "name": "Darshan" }

19. setTimeout and setInterval

// setTimeout — run code ONCE after a delay (milliseconds)
setTimeout(function() {
  console.log("Runs after 2 seconds");
}, 2000);

// setTimeout with arrow function
setTimeout(() => console.log("Hello!"), 1000);

// setInterval — run code REPEATEDLY every N milliseconds
const id = setInterval(() => {
  console.log("Runs every 1 second");
}, 1000);

// Stop the interval
clearInterval(id);

// Cancel a timeout before it fires
const t = setTimeout(() => console.log("Never runs"), 5000);
clearTimeout(t);

20. Error Handling — try / catch / finally

try {
  // code that might throw an error
  let result = 10 / 0;
  JSON.parse("invalid json {"); // throws SyntaxError
} catch (error) {
  // runs if an error is thrown inside try
  console.log(error.message); // "Unexpected token i in JSON..."
  console.log(error.name);    // "SyntaxError"
} finally {
  // ALWAYS runs — error or not
  console.log("Cleanup done");
}

// Throw your own error
function divide(a, b) {
  if (b === 0) throw new Error("Cannot divide by zero");
  return a / b;
}
🔑 Key Fact
try — monitored block. catch — runs only on error. finally — always runs regardless of error. finally is commonly used for cleanup (closing files, stopping loaders).

21. Browser Dialogs — prompt(), alert(), confirm()

alert("Hello!");
// Shows a message box. Returns undefined.

let name = prompt("What is your name?");
// Shows input box. Returns the string entered, or null if cancelled.

let confirmed = confirm("Are you sure?");
// Shows OK/Cancel dialog. Returns true (OK) or false (Cancel).

console.log(typeof prompt("test")); // "string" or "object" (null)
FunctionReturnsUse for
alert(msg)undefinedShowing messages
prompt(msg)string or nullGetting user input
confirm(msg)true or falseYes/No decisions

Practice Questions — Output Prediction & Concepts

Question 1
What is the output of the following code?
console.log(1 + "2" + 3);
  1. 6
  2. "123"
  3. "15"
  4. NaN
✅ B) "123" — 1 + "2" hits a string so becomes "12", then "12" + 3 = "123". Left-to-right evaluation.
Question 2
What does typeof null return?
  1. "null"
  2. "undefined"
  3. "object"
  4. "string"
✅ C) "object" — This is a well-known historic bug in JavaScript that was never fixed to preserve backward compatibility.
Question 3
What does typeof NaN return?
  1. "NaN"
  2. "undefined"
  3. "boolean"
  4. "number"
✅ D) "number" — NaN stands for "Not a Number" but is paradoxically of type "number". Always a top exam question.
Question 4
What is the output?
console.log(0.1 + 0.2 == 0.3);
  1. true
  2. false
  3. NaN
  4. undefined
✅ B) false — Due to floating-point precision, 0.1 + 0.2 equals 0.30000000000000004, not exactly 0.3.
Question 5
What is the output?
var x = 5;
console.log(x++);
console.log(x);
  1. 5, 5
  2. 6, 6
  3. 5, 6
  4. 6, 5
✅ C) 5, 6 — Post-increment x++ returns the current value (5) THEN increments. Next line x is now 6.
Question 6
What is the output?
console.log(a);
var a = 10;
  1. 10
  2. ReferenceError
  3. null
  4. undefined
✅ D) undefined — var a is hoisted to the top and initialised as undefined. The assignment a = 10 happens later.
Question 7
What is the output?
console.log(1 == "1");
console.log(1 === "1");
  1. true, true
  2. false, false
  3. true, false
  4. false, true
✅ C) true, false — == converts "1" to number 1 before comparing (equal). === checks type too: number ≠ string (not equal).
Question 8
What is the output?
console.log("5" - 3);
  1. "53"
  2. "5-3"
  3. 2
  4. NaN
✅ C) 2 — The - operator only does subtraction (no string concatenation). "5" is coerced to number 5, then 5 - 3 = 2.
Question 9
What is the output?
let arr = [1, 2, 3, 4];
let result = arr.filter(x => x > 2);
console.log(result);
  1. [1, 2]
  2. [3, 4]
  3. [2, 3, 4]
  4. true
✅ B) [3, 4] — filter returns a new array with elements where the callback returns true. Only 3 and 4 are greater than 2.
Question 10
What is the output?
let arr = [1, 2, 3];
console.log(arr.map(x => x * 2));
console.log(arr);
  1. [2, 4, 6], [2, 4, 6]
  2. [2, 4, 6], [1, 2, 3]
  3. [1, 2, 3], [2, 4, 6]
  4. [2, 4, 6], undefined
✅ B) [2, 4, 6], [1, 2, 3] — map does NOT mutate the original array. It returns a new array. The original arr is unchanged.
Question 11
What is the output?
function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}
const add5 = makeAdder(5);
console.log(add5(3));
  1. undefined
  2. 3
  3. 5
  4. 8
✅ D) 8 — This is a closure. add5 "closes over" x = 5. When called with 3, it returns 5 + 3 = 8.
Question 12
What is the output?
console.log(NaN === NaN);
  1. true
  2. false
  3. undefined
  4. TypeError
✅ B) false — NaN is the only value in JavaScript that is not equal to itself. Use isNaN() or Number.isNaN() to check for NaN.
Question 13
What is the output?
let a = 10;
function test() {
  console.log(a);
  var a = 20;
}
test();
  1. 10
  2. 20
  3. undefined
  4. ReferenceError
✅ C) undefined — Inside test(), var a is hoisted within the function scope. At console.log(a), the local a exists but is undefined (not yet assigned). The outer a = 10 is shadowed.
Question 14
What is the output?
console.log(true + true + "1");
  1. "111"
  2. 3
  3. "21"
  4. "true true 1"
✅ C) "21" — Left to right: true + true1 + 12 (both booleans convert to numbers). Then 2 + "1""21" (string concatenation).
Question 15
Which of the following values is TRUTHY in JavaScript?
  1. 0
  2. ""
  3. []
  4. null
✅ C) [] — An empty array is truthy in JavaScript. Only these 6 values are falsy: false, 0, "", null, undefined, NaN. Empty arrays and objects are NOT falsy.
Question 16
What is the output?
let arr = [10, 20, 30];
console.log(arr.indexOf(20));
console.log(arr.indexOf(99));
  1. 1, 0
  2. 2, -1
  3. 1, -1
  4. 20, undefined
✅ C) 1, -1 — indexOf returns the index of the element (20 is at index 1). If not found, it returns -1 (99 is not in the array).
Question 17
What is the output?
console.log(typeof undefined === typeof null);
  1. true
  2. false
  3. undefined
  4. TypeError
✅ B) false — typeof undefined is "undefined". typeof null is "object". "undefined" === "object" is false.
Question 18
What is the output?
let s = "Hello, World";
console.log(s.substring(7, 12));
  1. "Hello"
  2. "World"
  3. "orld"
  4. "World,"
✅ B) "World" — substring(7, 12) extracts characters from index 7 up to (but not including) index 12. H(0)e(1)l(2)l(3)o(4),(5) (6)W(7)o(8)r(9)l(10)d(11) → "World".
Question 19
What is the output?
const obj = { name: "test" };
const key = "name";
console.log(obj.key);
console.log(obj[key]);
  1. "test", "test"
  2. undefined, "test"
  3. "test", undefined
  4. undefined, undefined
✅ B) undefined, "test" — obj.key looks for a property literally named "key" (not the variable) → undefined. obj[key] uses the variable's value "name" → obj["name"] → "test".
Question 20
What is the output?
let x = 10;
let y = 3;
console.log(x % y);
console.log(x ** y);
  1. 3, 30
  2. 1, 1000
  3. 3, 1000
  4. 1, 30
✅ B) 1, 1000 — % is modulo: 10 ÷ 3 = 3 remainder 1. ** is exponentiation: 10³ = 1000.