Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
11 views

Debounce _ JavaScript Interview Questions with Solutions

The document explains the concept of debouncing in JavaScript, which limits how often a function can be executed over time by waiting for a specified duration after the last call. It provides an example of implementing a debounce function that utilizes setTimeout to manage the timing of function calls and discusses the importance of maintaining the correct context for 'this' when invoking the callback. Additionally, it touches on edge cases and best practices for implementing debounce and mentions related concepts like throttle.

Uploaded by

Parth Tiwari
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Debounce _ JavaScript Interview Questions with Solutions

The document explains the concept of debouncing in JavaScript, which limits how often a function can be executed over time by waiting for a specified duration after the last call. It provides an example of implementing a debounce function that utilizes setTimeout to manage the timing of function calls and discusses the importance of maintaining the correct context for 'this' when invoking the callback. Additionally, it touches on edge cases and best practices for implementing debounce and mentions related concepts like throttle.

Uploaded by

Parth Tiwari
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3

12 // t = 100: increment() was invoked and i is now 1.

Debounce debouncedIncrement() is called multiple times.


Yangshun Tay Medium 15 mins
Ex-Meta Staff Engineer 1 let i = 0;
8.07k done 2 Interviews
function increment() {
3 i++;

Debouncing is a technique used to control how many times we allow a function to 4 }

be executed over time. When a JavaScript function is debounced with a wait time
5 const debouncedIncrement = debounce(increment, 100);
6
of X milliseconds, it must wait until after X milliseconds have elapsed since the 7 // t = 0: Call debouncedIncrement().
debounced function was last called. You almost certainly have encountered 8 debouncedIncrement(); // i = 0

debouncing in your daily lives before — when entering an elevator. Only after X 9

duration of not pressing the "Door open" button (the debounced function not 10
11
// t = 50: i is still 0 because 100ms have not passed.
// Call debouncedIncrement() again.
being called) will the elevator door actually close (the callback function is 12 debouncedIncrement(); // i = 0
executed). 13
14 // t = 100: i is still 0 because it has only
Implement a debounce function which accepts a callback function and a wait 15 // been 50ms since the last debouncedIncrement() at t = 50.

duration. Calling debounce() returns a function which has debounced invocations 16

of the callback function following the behavior described above. 17


18
// t = 150: Because 100ms have passed since
// the last debouncedIncrement() at t = 50,
19 // increment was invoked and i is now 1 .

Examples
1 let i = 0;
Follow Up
2 function increment() {
Debounce with a cancel() method to cancel delayed invocations and a
flush() method to immediately invoke them.
3 i++;
4 }
5 const debouncedIncrement = debounce(increment, 100); Implement throttle, which is similar to debounce but a little different.
6

Reading
7 // t = 0: Call debouncedIncrement().
8 debouncedIncrement(); // i = 0
9
10 // t = 50: i is still 0 because 100ms have not passed. Debounce on Lodash Documentation
11
Companies 2) Calls the callback function with the right parameters
Google Lyft Walmart Yelp Tiktok ByteDance Microsoft Debounced functions are used like the original functions, so we should forward
LinkedIn Uber the value of this and function arguments when invoking the original callback
functions.
Coding and submission is not supported on mobile devices. Use a wider You may be tempted to use func(...args) but this will be lost if callback
screen to practice solving this question within the editor. functions are invoked that way. Hence we have use
Function.prototype.apply() / Function.prototype.call() which allows us to specify

this as the first argument.

Hide solution func.apply(thisArg, args)

func.call(thisArg, ...args)
Debounce, along with throttle, are among the most common front end interview
questions; it's the front end equivalent of inverting a binary tree. Hence you JavaScript TypeScript
should make sure that you are very familiar with the question.

Solution
1 /**
2 * @param {Function} func
GFE 75 1/70 Mark complete 3 * @param {number} wait
Given that there's a wait duration before the function can be invoked, we know 4 * @return {Function}

that we will need a timer, and setTimeout is the first thing that comes to mind. 5
6
*/
export default function debounce(func, wait = 0) {

We will also need to return a function which wraps around the callback function 7 let timeoutID = null;

parameter. This function needs to do a few things:


8 return function (...args) {
9 // Keep a reference to `this` so that
10 // func.apply() can access it.

1) Debounce invocation 11
12
const context = this;
clearTimeout(timeoutID);
It invokes the callback function only after a delay of wait . This is performed 13

using setTimeout . Since we might need to clear the timer if the debounced 14 timeoutID = setTimeout(function () {

function is called again while there's a pending invocation, we need to retain 15


16
timeoutID = null; // Not strictly necessary but good to do this.
func.apply(context, args);
a reference to a timeoutID , which is the returned value of setTimeout . 17 }, wait);

If the function is called again while there's a pending invocation, we should 18 };

cancel existing timers and schedule a new timer for the delayed invocation 19 }

with the full wait duration. We can cancel the timer via
clearTimeout(timeoutID) .
Edge Cases Also, we should not implement the returned function using an arrow function for
reasons mentioned above. The this value of the returned function needs to be
The main pitfall in this question is invoking the callback function with the correct dynamically determined when executed.
this , the value of this when the debounced function was called. Since the

callback function will be invoked in a timeout, we need to ensure that the first Read this article for a more in-depth explanation.
argument to func.apply() / func.call() is the right value. There are two ways to
achieve this: Techniques
1. Use another variable to keep a reference to this and access this via that Using setTimeout .
variable from within the setTimeout callback. This is the traditional way of Closures.
preserving this before arrow functions existed.
How this works.
2. Use an arrow function to declare the setTimeout callback where the this
value within it has lexical scope. The value of this within arrow functions is Invoking functions via Function.prototype.apply() / Function.prototype.call() .
bound to the context in which the function is created, not to the environment
in which the function is called. Notes
clearTimeout() is a forgiving function and passing an invalid ID to clearTimeout()
silently does nothing; no exception is thrown. Hence we don't have to check for
timeoutID === null before using clearTimeout() .
1 /**
2 * @callback func
3 * @param {number} wait
4
5
* @return {Function}
*/
Resources
6
7
export default function debounce(func, wait = 0) {
let timeoutID = null;
Debouncing and Throttling Explained Through Examples
8 return function (...args) { Implementing Debounce in JavaScript
9
10
clearTimeout(timeoutID);
clearTimeout() - Web APIs | MDN
11 timeoutID = setTimeout(() => {
12 timeoutID = null; // Not strictly necessary but good to include.
13 // Has the same `this` as the outer function's
14 // as it's within an arrow function.
15 func.apply(this, args);
16 }, wait);
17 };
18 }

You might also like