Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
🛡️ Days 23–27 – Professional JavaScript  ·  दिन 24

दिन 24: Higher-Order Functions, Debounce और Throttle

⏱ 95 min📶 Pro🎯 100% self-study
दिन 24 / 30

✅ आज आप सीखेंगे

  • Higher-order functions: functions लेना या लौटाना
  • Composition, pipe और currying
  • Immutability: बिना mutate किए data update
  • Debounce: user के रुकने तक इंतज़ार
  • Throttle: हर N ms में अधिकतम एक बार

🏢 असली दुनिया में

Live search box हर keystroke पर API बुलाता है: “kaju katli” लिखने पर 10 requests जाती हैं, नतीजे झिलमिलाते हैं, और shared server पर दुकान rate limits से टकराती है। Debounce 10 lines में इसे ठीक करता है – और “debounce लागू करें” India में सबसे आम front-end interview coding सवालों में है।

Higher-order functions

JavaScript
// Takes a function
function repeat(times, action) { for (let i = 1; i <= times; i++) action(i); }
repeat(3, n => console.log(`Box ${n} packed`));

// Returns a function
const discount = percent => price => Math.round(price * (1 - percent / 100));
const festival = discount(15);
console.log([900, 650, 500].map(festival));

// Wraps a function to add behaviour (a "decorator")
function logged(fn) {
  return (...args) => {
    const result = fn(...args);
    console.log(`${fn.name}(${args.join(', ')}) → ${result}`);
    return result;
  };
}
const addGst = function addGst(amount) { return Math.round(amount * 1.05); };
logged(addGst)(1800);
Box 1 packed Box 2 packed Box 3 packed [ 765, 553, 425 ] addGst(1800) → 1890

Composition, pipe और currying

JavaScript
const pipe = (...fns) => input => fns.reduce((value, fn) => fn(value), input);

const subtotal = cart => cart.reduce((s, i) => s + i.price * i.qty, 0);
const applyCoupon = code => amount => (code === 'SWEET10' ? amount * 0.9 : amount);
const addDelivery = amount => (amount >= 1500 ? amount : amount + 60);
const round = amount => Math.round(amount);

const checkoutTotal = pipe(subtotal, applyCoupon('SWEET10'), addDelivery, round);
console.log(checkoutTotal([{ price: 900, qty: 2 }]));       // 1800 → 1620 → 1620
console.log(checkoutTotal([{ price: 500, qty: 1 }]));       // 500 → 450 → 510

// currying: f(a, b, c) → f(a)(b)(c)
const curry = fn => function c(...args) { return args.length >= fn.length ? fn(...args) : (...more) => c(...args, ...more); };
const price = curry((rate, kg, gst) => Math.round(rate * kg * (1 + gst)));
const kajuPrice = price(900);
console.log(kajuPrice(2)(0.05), kajuPrice(0.5, 0.05));
1620 510 1890 473

Immutability: data को उसी जगह कभी न बदलें

JavaScript
const cart = { customer: 'Aarti', items: [{ id: 1, qty: 1 }, { id: 4, qty: 2 }] };

// ❌ mutating – other parts of the app holding "cart" change silently
// cart.items[0].qty = 5;

// ✅ create new objects/arrays for what changed
const updated = {
  ...cart,
  items: cart.items.map(item => (item.id === 1 ? { ...item, qty: item.qty + 1 } : item)),
};
const removed = { ...cart, items: cart.items.filter(i => i.id !== 4) };
const added = { ...cart, items: [...cart.items, { id: 7, qty: 1 }] };

console.log(cart.items[0].qty, updated.items[0].qty);
console.log(removed.items.length, added.items.length, cart.items.length);
console.log(cart.items[1] === updated.items[1]);   // unchanged parts are shared (cheap)

const deepCopy = structuredClone(cart);              // full independent copy when needed
deepCopy.items[0].qty = 99;
console.log(cart.items[0].qty);
1 2 1 3 2 true 1
🧠 React को इसकी परवाह क्यों

React references की तुलना (old === new) से तय करता है कि re-render करना है या नहीं। Array mutate करने पर reference वही रहता है और screen update नहीं होती। इसलिए React और Redux में immutable updates ज़रूरी हैं।

Debounce: रुकने का इंतज़ार

JavaScript
function debounce(fn, delay) {
  let timer;                                   // closure (Day 16)
  return function (...args) {
    clearTimeout(timer);                       // every new call cancels the previous one
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

const search = debounce(q => console.log(`🔎 API call for "${q}"`), 300);

// simulate typing "kaju" quickly, a pause, then " katli"
const typed = ['k', 'ka', 'kaj', 'kaju', 'kaju ', 'kaju k', 'kaju ka', 'kaju katli'];
const times = [0, 80, 160, 240, 700, 780, 860, 940];
typed.forEach((text, i) => setTimeout(() => search(text), times[i]));
// only 2 API calls instead of 8
🔎 API call for "kaju" 🔎 API call for "kaju katli"

Throttle: हर अंतराल में अधिकतम एक बार

JavaScript
function throttle(fn, interval) {
  let last = 0, timer;
  return function (...args) {
    const now = Date.now();
    const remaining = interval - (now - last);
    if (remaining <= 0) {
      last = now;
      fn.apply(this, args);                    // run immediately
    } else {
      clearTimeout(timer);
      timer = setTimeout(() => { last = Date.now(); fn.apply(this, args); }, remaining);   // and once at the end
    }
  };
}

let calls = 0;
const onScroll = throttle(y => console.log(`update sticky header at y=${y} (call ${++calls})`), 200);
for (let i = 0; i <= 20; i++) setTimeout(() => onScroll(i * 50), i * 30);   // 21 scroll events over 600 ms
update sticky header at y=0 (call 1) update sticky header at y=300 (call 2) update sticky header at y=650 (call 3) update sticky header at y=1000 (call 4)
DebounceThrottle
चलता हैEvents N ms रुकने के बाद एक बारनियमित, हर N ms में अधिकतम एक बार
जैसेLift का दरवाज़ा जो सबके घुसने तक रुकेTraffic signal जो हर N सेकंड गाड़ियाँ छोड़े
कबSearch boxes, auto-save, resize-end, form validationScroll position, mousemove, drag, analytics pings
आम देरी250–400 ms100–250 ms

असली task: API पर debounced live search

HTML + JavaScript
<input id="q" placeholder="Type fast: kaju, ghewar, box…" aria-label="Search sweets" style="width:260px">
<p>API calls: <b id="calls">0</b> · keystrokes: <b id="keys">0</b></p>
<ul id="results" aria-live="polite"></ul>

<script>
const API = 'https://codingeasily.in/api/sweets/';
let calls = 0, keys = 0, latest = 0;

function debounce(fn, delay) {
  let t;
  return (...args) => { clearTimeout(t); t = setTimeout(() => fn(...args), delay); };
}

async function search(q) {
  const id = ++latest;                                // ignore out-of-order responses
  document.querySelector('#calls').textContent = ++calls;
  const res = await fetch(`${API}?q=${encodeURIComponent(q)}`);
  const data = await res.json();
  if (id !== latest) return;                          // a newer search already started
  document.querySelector('#results').innerHTML =
    data.map(p => `<li>${p.name} – ₹${p.price}</li>`).join('') || '<li>No match</li>';
}

const debounced = debounce(q => { if (q.trim()) search(q.trim()); }, 300);
document.querySelector('#q').addEventListener('input', e => {
  document.querySelector('#keys').textContent = ++keys;
  debounced(e.target.value);
});
</script>
▶  Type quickly – keystrokes climb, API calls stay low

🏅 आज के Job Skills

✔ Higher-order functions और decorators लिखना✔ pipe और currying से logic जोड़ना✔ Objects और arrays immutably update करना✔ Debounce और throttle लिखना और चुनना

Practice tasks

🏋️ Practice – ख़ुद करें

Task 1: memoizeAsync(fn) लिखें जो async function के नतीजे argument से cache करे ताकि दोहराई searches API दोबारा न बुलाएँ।
Solution देखें
JavaScript
function memoizeAsync(fn) {
  const cache = new Map();
  return arg => {
    if (!cache.has(arg)) cache.set(arg, fn(arg).catch(err => { cache.delete(arg); throw err; }));
    return cache.get(arg);
  };
}
let apiCalls = 0;
const fakeApi = q => new Promise(r => setTimeout(() => r(`results for ${q} (call ${++apiCalls})`), 50));
const cachedSearch = memoizeAsync(fakeApi);
(async () => {
  console.log(await cachedSearch('kaju'));
  console.log(await cachedSearch('kaju'));
  console.log(await cachedSearch('ghewar'));
})();
results for kaju (call 1) results for kaju (call 1) results for ghewar (call 2)
Task 2: Nested order immutably update करें: id 4 वाले item की qty 3 करें और “gift” flag जोड़ें, original छुए बिना।
Solution देखें
JavaScript
const order = { id: 1042, customer: { name: 'Aarti' }, items: [{ id: 1, qty: 1 }, { id: 4, qty: 1 }] };
const next = {
  ...order,
  gift: true,
  items: order.items.map(i => (i.id === 4 ? { ...i, qty: 3 } : i)),
};
console.log(JSON.stringify(order));
console.log(JSON.stringify(next));
console.log(order.customer === next.customer);
{"id":1042,"customer":{"name":"Aarti"},"items":[{"id":1,"qty":1},{"id":4,"qty":1}]} {"id":1042,"customer":{"name":"Aarti"},"items":[{"id":1,"qty":1},{"id":4,"qty":3}],"gift":true} true
Task 3: Debounce में leading option जोड़ें: debounce(fn, ms, { leading: true }) पहली call पर तुरंत चले, फिर इंतज़ार करे।

Quick quiz

🧠 Quick Quiz – ख़ुद को जाँचें

1. Higher-order function…
map, filter, debounce…
2. Search box के लिए सबसे अच्छा:
रुकने का इंतज़ार।
3. Scroll position updates के लिए सबसे अच्छा:
नियमित updates।
4. कौन सा update immutable है?
नया array।
5. debounce किस पर निर्भर है?
Timer closure में रहता है।

Interview corner

💼 Interview Corner

Debounce लागू कीजिए।

function debounce(fn, ms) { let t; return function (...args) { clearTimeout(t); t = setTimeout(() => fn.apply(this, args), ms); }; } – हर call timer reset करती है तो fn तभी चलता है जब calls ms तक रुकें; leading/trailing options और cancel() का ज़िक्र करें।

असली उदाहरण के साथ debounce बनाम throttle?

Debounce: autocomplete search – लिखना रुकने के बाद एक बार। Throttle: infinite-scroll position या window resize – event चलते रहने तक स्थिर अधिकतम दर पर।

सारांश

  • Functions values हैं: दें, लौटाएँ, लपेटें।
  • pipe/compose और currying छोटे टुकड़ों से logic बनाते हैं।
  • spread/map/filter से update; deep copies के लिए structuredClone।
  • “रुकने के बाद” के लिए debounce, “हर N ms में अधिकतम” के लिए throttle।
➡️ आगे

Day 25: DOM performance और patterns – तेज़ rendering, बड़े पैमाने पर event delegation, requestAnimationFrame और lazy loading।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

क्या debounce के लिए lodash लूँ?
असली projects में lodash.debounce/throttle अच्छी तरह tested हैं और edge cases संभालते हैं। ख़ुद लिखना आना interviews जाँचते हैं।
क्या functional programming OOP से बेहतर है?
कोई नहीं – आधुनिक JavaScript दोनों मिलाता है: कुछ models के लिए classes, logic और UI state के लिए छोटे pure functions और immutable data।
← JavaScript (30 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicदिन 25: DOM Performance और Patterns आपकी प्रगति: 24 / 30 (80%) · Lesson 25 / 30 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें