Taught in teaching order — start at the top, work down. Engine architecture → variables → operators →
equality → truthy/falsy → control flow → loops → arrays → objects → functions → this →
arrow / IIFE / rest → callbacks → assignments. Hand-drawn diagrams for the tricky bits, key concepts on
the left, code samples in the middle, interview-style quiz on the right.
01JavaScript & V8 Engine
JS is a high-level, interpreted, dynamically-typed language. In the browser it runs on a JS engine — Chrome and Node.js use V8. V8 takes your source, builds a syntax tree, runs it in an interpreter, and JIT-compiles the hot paths to native machine code.
Hot code = looped or often-called functions → TurboFan compiles to native, 10-100× faster on next call.
functionadd(a, b) {
return a + b;
}
for (let i = 0; i < 1_000_000; i++) {
add(2, 3); // called millions of times → marked hot → JIT compiled
}
02var · let · const · Hoisting · typeof
Three keywords to declare. Two scopes (function vs block). One quirk called hoisting that trips up most candidates. And a famous bug: typeof null === 'object'.
var = function scope + auto undefined. let/const = block scope + Temporal Dead Zone until the line you wrote.
var: function-scoped, hoisted & auto-initialised to undefined, allows re-declaration.
let: block-scoped, hoisted but in Temporal Dead Zone until declaration — access before throws ReferenceError.
const: block-scoped, must be initialised at declaration, cannot be re-assigned (the binding, not the value — object props can still mutate).
Non-primitives: Object, Array, Function — passed by reference.
typeof null === 'object' — a 1995 bug never fixed for backward compat. NaN is 'number'.
var vs let scope
functionscopeTest() {
if (true) {
var v = 'I am var';
let l = 'I am let';
}
console.log(v); // 'I am var' — function-scoped, leaks out of the if
console.log(l); // ReferenceError — block-scoped
}
Every math operator except+ coerces strings to numbers. + is the trickster — if either side is a string, it concatenates. Template literals (backticks) replace messy string concatenation.
+ is dual-purpose: math or concatenation. If either side is a string, it concatenates.
Every other math operator (- * / % **) coerces strings to numbers — '5' - 2 === 3.
Unary + converts: +'42' === 42; +'abc' === NaN.
Template literals (backticks) support multi-line strings + ${expr} interpolation.
Prefix++a: increment first, return new value. Postfixa++: return current, then increment.
let name = 'Aarav';
let age = 30;
// old way — fragile, lots of quotes
console.log('hello ' + name + ' you are ' + age);
// template literal — readable, multi-line OK
console.log(`hello ${name} you are ${age}`);
console.log(`sum = ${100 + 200}`); // expressions work
04== vs === · Loose vs Strict equality
Use === always — it compares value and type. == coerces and creates the weird table that interviewers love to ask about.
== coerces types before comparing. === never coerces — different types means false.
Famous coercions: true == 1, false == 0, '' == 0, [] == 0 — all true.
Three loop forms. while for unknown counts (polling). for for known counts (clean control). do-while when the body must run at least once.
do-while is the only loop where the body is guaranteed to run at least once.
while · unknown iteration count
let i = 1;
while (i <= 10) {
console.log(i);
i++;
}
for · known count, compact
for (let m = 1; m <= 10; m++) {
console.log(m);
}
// even numbersfor (let n = 1; n <= 10; n++) {
if (n % 2 === 0) console.log(n);
}
do-while · run body, then check
let p = 1;
do {
console.log(p);
p++;
} while (p <= 10);
// SDET wait-patternlet attempts = 0;
while (!(await button.isEnabled()) && attempts < 10) {
await page.waitForTimeout(500);
attempts++;
}
082D arrays · reverse · object references
Arrays of arrays = matrices. reverse() mutates in place. Two variables holding the same object share one memory entry — change via one, both see it.
Primitives live on the stack (copied by value). Objects/arrays live on the heap; variables hold a reference. Re-assigning a primitive copies; re-assigning an object shares the heap entry.
2D array = array of arrays. Access m[row][col]. Walk with nested for.
arr.reverse() mutates and returns the same array. Use [...arr].reverse() to keep the original.
[1,2] + [3,4] → '1,23,4' — both coerced to strings, then concatenated. Use arr1.concat(arr2) or [...arr1, ...arr2].
Object assignment copies the reference: let b = a; b.x = 5 changes a.x too.
Shallow vs deep copy: {...a} copies top-level only — nested objects still shared. Use structuredClone(a) for deep copy.
Matrix walk
let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
console.log(matrix[i][j]);
}
}
Reference sharing
let u1 = { name: 'ravi', age: 30 };
let u2 = u1; // same heap entry
u1.name = 'ravi-updated';
console.log(u2.name); // 'ravi-updated'// to make a true copylet u3 = { ...u1 }; // shallow — nested still sharedlet u4 = structuredClone(u1); // deep
09Object iteration · JSON · null handling
for...in over keys, for...of over array values, Object.entries(obj) when you want both. JSON.stringify / JSON.parse are the round-trip pair for API payloads. ?. protects you from crashing on null.
for (let k in obj) — iterates string keys (including inherited). Filter with obj.hasOwnProperty(k) if needed.
for (let v of arr) — iterates values. Works on arrays, strings, Maps, Sets.
Object.keys / .values / .entries return arrays — easy to combine with .forEach / .map / .filter.
JSON.stringify(obj, null, 2) serialises with 2-space indent. JSON.parse(s) creates a fresh copy (no shared refs).
Optional chaining obj?.a?.b returns undefined instead of crashing if any link is null/undefined.
Nullish coalescing a ?? b returns b only if a is null or undefined (unlike || which also fires on 0 / '').
// outbound: object → JSON stringconst body = JSON.stringify({ email: '[email protected]', role: 'sdet' });
await page.request.post('/api/users', { data: body });
// inbound: JSON string → objectconst res = await page.request.get('/api/users/1');
const user = JSON.parse(await res.text());
// optional chaining + nullish coalescingconst city = user?.address?.city ?? 'unknown';
10Functions · Heap / Stack · Call stack
Functions are first-class. Call them and a frame goes on the stack. Return and the frame pops. Recurse without a base case → "Maximum call stack size exceeded".
Four flavours: (1) no input/no return, (2) no input/return, (3) input/return, (4) multi-branch return.
Parameter = name in signature. Argument = value at call site. JS does not enforce parameter types.
Function.name / Function.length (= parameter count) are introspection helpers.
Each call pushes a frame onto the call stack (LIFO). Recurse without a base case → stack overflow.
Function objects themselves live on the heap; the variable holding the function reference lives on the stack.
Four function flavours
functiontest() { // (1) no input, no return
console.log('test');
}
functiongetTrainerName() { // (2) no input, returnreturn'TTA Instructor';
}
functionadd(a, b) { // (3) input + returnreturn a + b;
}
functiongetStudentMarks(name) { // (4) switch with multi-returnswitch (name.trim().toLowerCase()) {
case'ravi': return90;
case'pooja': return80;
default: return -1;
}
}
Type-coercion gotcha (no error)
functionadd(a, b) { return a + b; }
console.log(add(10, 'abc')); // '10abc' (string concat, not math)
console.log(add(10)); // NaN (b is undefined → 10 + undefined)// guard manually if math is requiredfunctionsafeAdd(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw newError('numbers only');
}
return a + b;
}
11Duplicate functions · Default params · Function expressions · this
JS has no function overloading — last declaration wins. Default params fill in missing args. Function expressions are not hoisted. this inside an object method refers to the object itself.
Two functions same name → the second overwrites the first silently.
Default params: function f(a, b = 10) { … }. Passing undefined uses the default; passing null does NOT.
Function declarations are hoisted; function expressions (assigned to variables) are not.
Inside an object method, this = the object. From a free call, this = undefined (strict) or the global object (sloppy).
Avoid losing this when passing methods around — bind it with fn.bind(obj) or wrap in an arrow.
A callback is a function passed as an argument. Array methods (forEach, map, filter, reduce) all take callbacks. This is the gateway to promises and async/await.
const add = (a, b) => a + b;
const sub = (a, b) => a - b;
const mul = (a, b) => a * b;
functioncalculator(a, b, op) {
returnop(a, b);
}
console.log(calculator(10, 20, add)); // 30
console.log(calculator(10, 20, (a, b) => a / b)); // 0.5
Array methods · the bread & butter
const nums = [1, 2, 3, 4, 5];
nums.forEach(n => console.log(n + 5)); // side effect onlyconst big = nums.filter(n => n > 3); // [ 4, 5 ]const doubled = nums.map(n => n * 2); // [ 2, 4, 6, 8, 10 ]const total = nums.reduce((acc, n) => acc + n, 0); // 15
Self-test questions taken from the course's Chapter-1-to-7 and Session-8-to-13 sets. Treat each like a flash-card: write the answer in your editor, then run it.
Chapters 1-7 · 70 questions
What is JavaScript? Compiled or interpreted?
Name three places JavaScript can run.
What is Node.js and why use it?
What is V8? Which browsers use it?
JS engines in Chrome, Firefox, Safari?
Browser engine vs JS engine — difference?
Command to check Node.js installation.
What is VS Code? Two useful extensions for JS.
Print "Hello JavaScript!" via console.log + Node.js.
Can JS run without a browser? How?
Three ways to declare variables.
Difference between let and const.
Can you reassign a const? What error?
What is hoisting? Show with var.
Using let before declaration — what error?
List all primitive types.
null vs undefined difference.
typeof for: 42, 'hello', true, null, undefined.
Number type range? Beyond range behaviour?
Declare var, let, const; print all three.
String concatenation example with +.
What are template literals?
Rewrite with template literal: 'My name is ' + name + ' and I am ' + age.
Single vs double vs backticks difference.
List basic math operators.
Result of 10 % 3? Modulus explanation.
Result of 2 ** 4?
What does += do? Example.
'Hello' + 5 = ? Result type?
Program: add two numbers, print with template literal.
== vs === difference.
5 == '5' vs 5 === '5' — why?
What is NaN? Example.
Check if value is NaN — use ===?
What is Infinity? Operation that produces it.
Infinity + 100 = ?
i++ vs ++i difference. Example.
let x = 5; let y = x++; — values of x and y?
What is type coercion? Example.
null == undefined vs null === undefined.
if-else syntax.
Purpose of else if. When use?
Program: positive / negative / zero check with if / else if / else.
What is the ternary operator? Example.
switch-case syntax. Forget break — what happens?
Day-name program (1=Monday, 2=Tuesday, …).
default case purpose. Required?
Set breakpoint in VS Code.
if-else vs switch-case — preference?
Ternary: check age >= 18, print 'Eligible' or 'Not Eligible'.
for-loop syntax. Three parts in parentheses?
for loop: print 1 to 10.
while vs do-while difference.
while loop: print 10 down to 1.
break and continue keywords — what do they do?
for loop: even numbers 1 to 20.
Falsy values — list all.
Truthy values — three examples.
for loop: sum 1 to 100.
while(true) without exit — danger? Avoid?
Create a 5-element array example.
Access third element. Index?
push() method. Example.
pop() method. Return value?
shift() vs unshift() difference.
splice() method. Remove 2 elements from index 1.
Find array element index. Not-found return?
length property usage.
Create 5-fruit array; add one to end; remove one from start; print result.
splice() vs slice() difference.
Sessions 8-13 · 72 questions
What is a 2D array? 3×2 example.
Access row 1, column 0 in a matrix.
Print all 2D array elements (nested for loops).
reverse() method — changes original?
Reverse [10, 20, 30, 40, 50]; print.
JS object definition — different from array?
Create a 'user' object: name, age, city, isActive.
Dot notation vs bracket notation — both examples.
Add a new property. Delete a property.
Nested object example. user.address with flat, zip, city.
user.address.flat return value.
Assign one object to another — same reference or copy?
Get all object keys — which method?
for...in loop: print all keys and values.
for...in vs for...of difference.
JSON.stringify() does what? Return type?
JSON.parse() does what? Return type?
Convert { name: 'Tom', age: 30 } to JSON string.
JSON string back to object; access name property.
Serialization vs deserialization.
Set object to null; access property — what happens?
Optional chaining operator ?. — how it helps null.
Calculator with rest params — add any number of values.
Callback not passed — what happens?
Reference page · TTA-rebranded · every code sample written against https://app.thetestingacademy.com/ patterns.
Push these snippets into your IDE, run with node fileName.js, and tweak. The diagrams above also exist as Excalidraw scenes you can open and remix.