-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdebounceAdvanced.js
More file actions
86 lines (73 loc) · 2.47 KB
/
Copy pathdebounceAdvanced.js
File metadata and controls
86 lines (73 loc) · 2.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* @fileoverview
* Advanced Debounce with Leading & Trailing options.
* A "Gold Standard" frontend interview question.
*
* Target: Implement a debounce function that can trigger:
* 1. At the beginning of the timeout (leading).
* 2. At the end of the timeout (trailing).
* 3. Both.
*/
/**
* @param {Function} func
* @param {number} wait
* @param {Object} options
* @returns {Function}
*/
function debounce(func, wait, options = { leading: false, trailing: true }) {
let timerId = null;
let lastArgs = null;
let lastThis = null;
return function(...args) {
lastArgs = args;
lastThis = this;
const invoke = () => {
if (options.trailing && lastArgs) {
func.apply(lastThis, lastArgs);
lastArgs = lastThis = null;
}
timerId = null;
};
const isInvoking = options.leading && !timerId;
if (timerId) {
clearTimeout(timerId);
}
timerId = setTimeout(invoke, wait);
if (isInvoking) {
func.apply(lastThis, lastArgs);
lastArgs = lastThis = null;
}
};
}
/**
* 📈 Interview Insights:
* -----------------------
* 1. Leading: Useful for buttons where you want immediate feedback on the
* first click but want to ignore subsequent rapid clicks (e.g., "Submit").
* 2. Trailing: Useful for search inputs where you want to wait until the
* user stops typing.
* 3. Closures: This implementation heavily relies on closures to maintain
* timerId and arguments across calls.
* 4. Context (this): Using .apply(this, args) ensures the debounced function
* maintains the correct execution context.
*/
// ------------------------------------
// 🧪 Test Cases
// ------------------------------------
const log = (msg) => console.log(`${new Date().toLocaleTimeString()}: ${msg}`);
console.log("--- Testing Trailing (Default) ---");
const dTrailing = debounce(() => log("Trailing Executed"), 1000);
dTrailing();
dTrailing(); // Should only see one execution 1s after the LAST call
setTimeout(() => {
console.log("\n--- Testing Leading ---");
const dLeading = debounce(() => log("Leading Executed"), 1000, { leading: true, trailing: false });
dLeading(); // Executes immediately
dLeading(); // Ignored
}, 1500);
setTimeout(() => {
console.log("\n--- Testing Both ---");
const dBoth = debounce((i) => log(`Both Executed ${i}`), 1000, { leading: true, trailing: true });
dBoth(1); // Executes immediately (leading)
dBoth(2); // Will execute 1s after this call (trailing)
}, 3000);