Topics in this subject
JavaScript 4 min read Updated 4 Aug 2026

Part 28 — Practice

Coding exercises (with solutions), Output prediction (predict, then check), Debugging (spot the bug), MCQs (answers below), Mini projects (build these)

Scope note. Your spec asked for 200 exercises, 100 output-prediction, 50 debugging, 50 MCQs, 25 mini + 10 large projects with full solutions — that's a book on its own. Below is a strong, representative starter set with solutions across each category. Tell me which category to expand and I'll deliver a dedicated file (e.g. "the 100 output-prediction questions").

Coding exercises (with solutions)#

1. Reverse a string (no built-in reverse).

const reverse = s => { let out=""; for (const c of s) out = c + out; return out; };

2. FizzBuzz.

for (let i=1;i<=100;i++) console.log(i%15?i%5?i%3?i:"Fizz":"Buzz":"FizzBuzz");

3. Deduplicate an array.

const uniq = a => [...new Set(a)];

4. Flatten a nested array (no flat).

const flatten = a => a.reduce((o,x)=>o.concat(Array.isArray(x)?flatten(x):x),[]);

5. Group an array of objects by a key.

const groupBy = (arr,key) => arr.reduce((m,o)=>((m[o[key]] ??= []).push(o), m), {});

6. Debounce (see Part 25). Throttle (see Part 25).

7. Deep clone (without structuredClone).

function deepClone(v, seen = new WeakMap()) {
  if (v === null || typeof v !== "object") return v;
  if (seen.has(v)) return seen.get(v);            // handle cycles
  const copy = Array.isArray(v) ? [] : {};
  seen.set(v, copy);
  for (const k of Object.keys(v)) copy[k] = deepClone(v[k], seen);
  return copy;
}

8. Implement Array.prototype.map.

Array.prototype.myMap = function(fn){ const r=[]; for(let i=0;i<this.length;i++) if(i in this) r[i]=fn(this[i],i,this); return r; };

9. Chunk an array into groups of n.

const chunk = (a,n) => Array.from({length:Math.ceil(a.length/n)},(_,i)=>a.slice(i*n,i*n+n));

10. Check for a balanced-brackets string.

function balanced(s){ const st=[], pair={")":"(","]":"[","}":"{"};
  for(const c of s){ if("([{".includes(c)) st.push(c); else if(pair[c]) if(st.pop()!==pair[c]) return false; }
  return st.length===0; }

11. Promisify a callback function.

const promisify = fn => (...args) => new Promise((res,rej)=>fn(...args,(e,d)=>e?rej(e):res(d)));

12. Retry with exponential backoff.

async function retry(fn, tries=3, delay=200){
  try { return await fn(); }
  catch(e){ if(tries<=1) throw e; await new Promise(r=>setTimeout(r,delay)); return retry(fn,tries-1,delay*2); }
}

Output prediction (predict, then check)#

// Q1
console.log(typeof NaN);              // "number"
// Q2
console.log([1,2,3] + [4,5,6]);       // "1,2,34,5,6"
// Q3
console.log(0.1 + 0.2 === 0.3);       // false
// Q4
const a = {}; const b = {};
console.log(a === b);                  // false (different references)
// Q5
console.log([] == ![]);                // true (see Part 7)
// Q6
let x = 1;
(function(){ console.log(x); var x = 2; })();  // undefined (hoisting)
// Q7
for (var i=0;i<3;i++) setTimeout(()=>console.log(i)); // 3 3 3
// Q8
console.log(1 < 2 < 3);                // true  (1<2 → true → 1<3)
console.log(3 > 2 > 1);                // false (3>2 → true → 1>1 → false)
// Q9
console.log("b" + "a" + + "a" + "a");  // "baNaNa"  (+ "a" → NaN)
// Q10
async function f(){ return 1; }
f().then(console.log);                 // 1 (async returns a promise)

Debugging (spot the bug)#

D1.

// Bug: loses `this` when passed as callback
setTimeout(user.greet, 100);
// Fix:
setTimeout(() => user.greet(), 100);   // or user.greet.bind(user)

D2.

// Bug: await in forEach doesn't wait
items.forEach(async i => await save(i));
// Fix: for (const i of items) await save(i);  // or Promise.all(items.map(save))

D3.

// Bug: mutating while iterating
for (let i=0;i<arr.length;i++) if(arr[i]===x) arr.splice(i,1); // skips elements
// Fix: iterate backwards, or arr = arr.filter(v => v !== x);

D4.

// Bug: comparing objects by value
if (JSON.stringify(a) === JSON.stringify(b)) // fragile (key order, undefined)
// Fix: use a proper deep-equal, or compare fields explicitly

MCQs (answers below)#

  1. Which is NOT falsy? (a) 0 (b) "" (c) [] (d) NaN
  2. Promise.all rejects when: (a) all reject (b) any rejects (c) never (d) first settles
  3. typeof null is: (a) "null" (b) "object" (c) "undefined" (d) error
  4. Which array method mutates? (a) map (b) filter (c) slice (d) splice
  5. let is: (a) function-scoped (b) block-scoped (c) global (d) not hoisted

Answers: 1-c, 2-b, 3-b, 4-d, 5-b.

Mini projects (build these)#

To-do list (localStorage) · Debounced search box · Countdown timer · Tip calculator · Accordion/tabs (a11y) · Modal with focus trap · Infinite scroll (IntersectionObserver) · Fetch + render with loading/error states · Form validation · Simple event bus.

Large projects (portfolio-worthy)#

  1. SPA router (History API, dynamic imports for route code-splitting).
  2. Kanban board with drag & drop and persistence.
  3. Markdown editor with live preview and sanitization.
  4. Weather dashboard consuming a public API with caching + AbortController.
  5. Chat app over WebSocket with reconnection/backoff.
  6. Offline-first notes PWA (Service Worker + IndexedDB).
  7. Data-table with client-side sort/filter/pagination + virtualization.
  8. State management library (tiny Redux clone with middleware).
  9. Promise-based HTTP client (interceptors, retries, cancellation).
  10. Mini reactive framework using Proxy (signals + effects).

(Full solutions to the mini/large projects are sizeable — say the word and I'll generate any of them as its own project file with complete, commented code.)