Data Types & Functions
Data Types & Functions: Primitive (Stack) vs Reference (Heap) Types JavaScript data types split into two groups and understanding this distinction is critical in test automation.
Primitive (Stack) vs Reference (Heap) Types
JavaScript data types split into two groups and understanding this distinction is critical in test automation. Primitive types (String, Number, Boolean, Null, Undefined, Symbol, BigInt) are like postage stamps: the value is carried on the stamp itself, and copying creates a fully independent duplicate. Reference types (Object, Array, Function) are like a key to a mailbox: copying the key gives two keys that open the same box — if one person changes the contents, the other sees the change too. Why does this matter? In Java the primitive (`int`, `boolean`) vs reference (`List`, `Map`) distinction is identical and causes the same issues: `int a = b` copies the value, `List a = b` copies the reference. Critical QA scenario: if you share a test data object between two tests and one mutates it, the other test breaks — the classic source of flaky tests. Solution: use `JSON.parse(JSON.stringify(data))` for deep copy or spread `{...config}` for shallow copy.
Object Reference — The "Mailbox Key" in Action
`const config = { retries: 3 }` creates an object on the Heap. `config` holds the object's address (reference) — not the object itself.
`backup = config` copies the REFERENCE — it does NOT create a new object. `config` and `backup` now point to the SAME Heap object (two keys, one mailbox).
`backup.retries = 5` MUTATES the object on the Heap. `const backup` only prevents REASSIGNING the reference — not changing the object's CONTENTS.
`config.retries` also prints `5` — `config` was NEVER touched directly, but the change made via `backup` reflects on `config` too because they share the SAME object. This is the most common source of test-data contamination (flaky tests) in JS.
Primitive Types — 7 Building Blocks
3 Ways to Write Functions
Function Declaration vs Expression vs Arrow
// ─── 1. Function Declaration ───────────────────────────────── // Like Java's public static void / String methodName() // Hoisting: callable BEFORE it is defined function add(a, b) { return a + b; } console.log(add(3, 5)); // 8 // ─── 2. Function Expression ─────────────────────────────────── // Assigned to a variable; NO hoisting const multiply = function(a, b) { return a * b; }; console.log(multiply(4, 6)); // 24 // ─── 3. Arrow Function (ES6) ────────────────────────────────── // Concise syntax; does NOT inherit its own 'this' (key difference!) const divide = (a, b) => a / b; // single line → implicit return const greet = name => `Hello, ${name}!`; // single param → parentheses optional console.log(divide(10, 2)); // 5 console.log(greet("Hasan")); // Hello, Hasan!
Micro Lab: JavaScript QA coding practice
Replace the TODO line with the critical line from the expected solution. This is not a real runtime; the goal is to reinforce writing the correct structure in a controlled way.
Step by Step: JavaScript QA coding practice