functiondebounce(fn, delay){let timerId;returnfunction(...args){clearTimeout(timerId);
timerId =setTimeout(()=> fn.apply(this, args), delay);};}// Usage: only fire after user stops typing for 300msconst searchInput =document.querySelector("#search");
searchInput.addEventListener("input",debounce((e)=>{console.log("Searching:", e.target.value);},300));
Note Debouncing delays execution until activity stops for a given period. Ideal for search inputs, window resize handlers, and form validation.
functionthrottle(fn, interval){let lastTime =0;returnfunction(...args){const now =Date.now();if(now - lastTime >= interval){
lastTime = now;
fn.apply(this, args);}};}// Usage: fire at most once per 200ms during scrollwindow.addEventListener("scroll",throttle(()=>{console.log("Scroll position:",window.scrollY);},200));
Note Throttling ensures a function runs at most once per interval, even if triggered constantly. Use for scroll, mousemove, and resize events.
functionmemoize(fn){const cache =newMap();returnfunction(...args){const key =JSON.stringify(args);if(cache.has(key))return cache.get(key);const result = fn.apply(this, args);
cache.set(key, result);return result;};}const expensiveCalc =memoize((n)=>{console.log("Computing...");return n **2+Math.sqrt(n);});console.log(expensiveCalc(100));// "Computing..." then 10010console.log(expensiveCalc(100));// 10010 (cached, no log)
Note Caches results for repeated calls with the same arguments. Use JSON.stringify for simple keys. For complex args, consider a WeakMap-based approach.
Note Currying transforms a function of multiple arguments into a chain of single-argument functions. Enables partial application and reusable configurations.
Note Ensures only one instance of a class exists. In modern JavaScript, ES modules are natural singletons -- an exported object is shared across all importers.