Preparing for Frontend Interview

Subscribe to my newsletter and never miss my upcoming articles

Debounce

It is used to improved performance . Sometime a function is being called continuously . The Debounce technique allow us to "group" multiple sequential calls in a single one. For eg Suppose we have blog editor.We are editing the content of the blog.We have a autosave feature for most of the editor. When ever we add or delete a character, an API call is being made to save the content. Therefore whenever we edit a character it makes a call. This overburden our api server. To solve this problem we can use debounce. If we have multiple events triggered. We can either act on the leading event or the last event. So here in case we editor we will act on the last event ie when we stop writing the characters for particular time. Code:

const debounce = (cb,delay)=>{
    let timer ;
    return (...args)=>{
         clearTimeout(timer);
         timer = setTimeout(()=>{
                cb(...args);
         },delay)
    }
}

Usage:

const [text,setText]=useState("")

<input  type="text" value={text} onClick={this.handleInput}/>

const handleInput=(e)=>{
    setText(e.target.value);
    debounce(saveText,3000)
}

Explanation: debounce returns a function. We have scoped timer variable . The function that we are returning has two things clearTimeout and setTimeout.When debounce is triggered we are removing the old Timeout function and creating a new. Our callback will be triggered after delay time. If debounce is triggered again before delay time trigger the callback, then we are removing the Timeout. So callback will be triggered if no debounce event triggered between delay time.

if you want to dig more deeper learn about leading and trailing

Throttle

By using throttle, we don't allow to our function to execute more than once every X milliseconds.

The main difference between this and debouncing is that throttle guarantees the execution of the function regularly, at least every X milliseconds.

Eg: Suppose we have infinite scroll on our page. When we reach the bottom of the page we have an ajax call to fetch the data. So on scroll event we have are logic which checks whether we have reached the bottom of the page or not.If we don't have throttle on our callback function it will trigger on every scroll event.

window.addEventListener('scroll',()=>{
//Logic for checking the end of page and fetching the data
})

Implementation:

const throttle = (cb,delay)=>{
    let timer=null;
    return (...args)=>{
     if(timer===null)
         {
              cb(...args);
              timer = setTimeout(()=>{timer=null},delay);
         }
    }
}

Usage:

window.addEventListener('scroll',throttle(()=>{
//Logic for checking the end of page and fetching the data
},3000))

Explanation: throttle returns a function. We have scoped timer variable .Our return function checks if there was any setTimeout function already running.If its running the timer variable is not null else its null.On first call timer is null and it triggers the cb function and create a setTimeout function which makes timer variable not null. When throttle is triggered again , timer is not null and hence we wait till setTimeout function completes and makes timer variable null.

if you want to dig more deeper learn about leading and trailing

In summary:

  • debounce: Grouping a sudden burst of events (like keystrokes) into a single one.
  • throttle: Guaranteeing a constant flow of executions every X milliseconds. Like checking every 200ms your scroll position to trigger a CSS animation.

Polyfill( map,reduce,filter)

A polyfill is a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it.

  • map:
    Array.prototype.map = (cb)=>{
      let arrayList =[];
      for(let i=0;i<this.length;i++){
       arrayList.push(cb(this[i],i))
      }
      return arrayList;
    }
    
  • reduce

Array.prototype.reduce1= function(callback, initialValue) {
  var accumulator = initialValue === undefined ? undefined : initialValue

  for (var i = 0; i < this.length; i++) {
    if (accumulator !== undefined) {
      accumulator = callback.call(undefined, accumulator, this[i], i, this)
    } else {
      accumulator = this[i]
    }
  }
  return accumulator
} // our polyfill for reduce

let arr = [1,2,3]

let sumOfArr = arr.reduce(function(a, b) {
  return a + b
}, 0) // Initial Value is 0

console.log(sumOfArr)
// 6
  • filter:
Array.prototype.filter = function(callback, context) {
  arr = []
  for (var i = 0; i < this.length; i++) {
    if (callback.call(context, this[i], i, this)) {
      arr.push(this[i])
    }
  }
  return arr
}
let ret = arr.filter(function(data) {
  return data > 2 // providing the context here
})
console.log(ret)

Pure Functions

The definition of a pure function is:

  1. The function always returns the same result if the same arguments are passed in. It does not depend on any state, or data, change during a program’s execution. It must only depend on its input arguments.
  2. The function does not produce any observable side effects such as network requests, input and output devices, or data mutation.

What are Side effects?

Function should not interact with the outside world.That could be anything from changing a variable that exists outside the function, to calling another method from within a function,accessing a variable not in function internal scope.

Note: If a pure function calls a pure function this isn’t a side effect and the calling function is still pure. -pure eg

let P=10,R=20,T=2;
const simpleInterest = function(P,R,T){
    return (P*R*T)/100
}
  • impure eg
let P=10,R=20,T=2;
const simpleInterest = function(){
    return (P*R*T)/100//here we are directly accessing the outside variable
}

Webpack

Webpack takes modules and dependencies to generate static assets.

Concept:

  • Entry: An entry point indicates which module webpack should use to begin building out its internal dependency graph. After entering the entry point, webpack will figure out which other modules and libraries that entry point depends on (directly and indirectly).
  • Output: The output property tells webpack where to store the bundled files ,it defaults to ./dist. Basically, the entire app structure will get compiled into the folder that you specify in the output path.
  • Loaders: Loaders enable webpack to process more than just JavaScript files . They give you the ability to leverage webpack’s bundling capabilities for all kinds of files by converting them to valid modules that webpack can process. eg sass-loader(Loads a Sass/SCSS file and compiles it to CSS),file-loader(for images and files)
  • Plugins: Plugins range from bundle optimization and minification all the way to defining environment-like variables. The plugin interface is extremely powerful and can be used to tackle a wide variety of tasks.

TIP: All React component names must start with a capital letter. If you start a component name with a lowercase letter, it will be treated like a built-in element like a <div> or a <span> . This is because of the way JSX works. In JSX, rendering a component that begins with a lowercase letter compiles down to React.

No Comments Yet