Javascript Interview Questions on Closures - Lexical Scope, Output based Questions, Polyfills and more

Javascript Interview Questions on Closures - Lexical Scope, Output based Questions, Polyfills and more

So let's talk about Closures. This is a topic that most of the JavaScript developers are afraid of. Let's see What are these Closures actually are? This is also the most important topic in interviews.

P.S. : Please watch the video for better explanation. Javascript Interview Questions ( Closures ) This is written format for the video incase you want to follow along the tutorial.

closures-closures-everywhere.jpeg

Closure is a combination of function bundled together with it's lexical environment. It is a function that references variables in the outer scope from it's inner scope

To know more about Closures we need to know about Lexical scope.

What is Lexical scope?

A Lexical scope in JavaScript means that a variable defined outside a function can be accessible inside another function defined after the variable declaration. But the opposite is not true; the variables defined inside a function will not be accessible outside that function.

Let's see an example.

function foo() {
  var name = 'Roadside Coder'; // name is a local variable created by foo
  function displayName() { <----- A Closure // displayName() is the inner function
    alert(name); // variable used which is declared in the parent function
  }
  displayName();
}
foo();

Scope can be globally or locally defined. We have block scopes also now with ES6. For example : 👇🏻

// Global scope in here
var foo= function(){
     // local scope in here
}

Why do we use Closures?

Closures makes it possible for a function to have "private" variables. JavaScript closure is used to control what is and isn't in scope in a particular function, along with which variables are shared between sibling functions in the same containing scope.

function makeFunc() {
  var name = 'Roadside Coder';
  function displayName() {
    alert(name);
  }
  return displayName;
}

var myFunc = makeFunc();
myFunc();

Closure Scope chain

Closures have three scopes :

  • Local Scope (Own scope)

  • Outer Functions Scope

  • Global Scope

If an outer function is a nested function then the outer function's scope includes the enclosing scope of the outer function which creates a chain of function scopes.

Mostly asked Interview Questions for Closures

1. What are the advantages of Closures?

There are several advantages of using closures in JavaScript. Some of them are:

  • Closure enables the use of nested functions that are used to get the values created in the execution context of that of the parent function.

  • They can prove as a perfect solution while solving a problem of hierarchy in any program.

  • They have huge importance as far as functional programming is concerned. It solves the for loop problem of functional programming.

  • It is also used to simulate private scope for variables.

2. What is the difference between closure and scope?

When you declare a variable in a function, you can only access it in the function. These variables are said to be scoped to the function.If you define any inner function within another function, this inner function is called a closure. It retains access to the variables created in the outer function.

Whereas a scope in JavaScript defines what variables you have access to. There are two kinds of scope – global scope and local scope.

3. What will be the output for the following code snippet?

let count = 0;
(function immediate() {
  if (count === 0) {
    let count = 1;
    console.log(count); // Output ?
  }
  console.log(count); // Output?
})();

**Solution : **

1 and 0 is logged to the console.

The first statement let count = 0 declares a variable count.

immediate() is a closure that captures the count variable from the outer scope. Inside of the immediate() function scope count is 0.

However, inside the conditional, another let count = 1 declares a local variable count, which overwrites count from outer the scope. The first console.log(count)logs 1.

The second console.log(count) logs 0, since here count variable is accessed from the outer scope.

4. Can you create a function named createBase to show the below functionality?

var addSix = createBase(6);
addSix(10);// returns 16
addSix(21);// returns 27

Solution :

You can create a closure to keep the value passed to the function createBase even after the inner function is returned. The inner function that is being returned is created within an outer function, making it a closure, and it has access to the variables within the outer function, in this case the variable baseNumber.

function createBase(baseNumber) {
  return function(N) {
    // we are referencing baseNumber here even though it was declared
    // outside of this function. Closures allow us to do this in JavaScript
    return baseNumber + N;
  }
}

var addSix = createBase(6);
addSix(10);
addSix(21);

5.How do you optimise time using closures?

function find(index) {
    let a = [];
  for (let i = 0; i < 1000000; i++) { a[i]= i*i }

  console.log(a[index])
}

console.time("6");
find(6); // this takes 37ms
console.timeEnd("6");
console.time("12");
find(12); // this takes 135ms
console.timeEnd("12");

Solution :

function find() {
let a = [];
for (let i = 0; i < 1000000; i++) {
 a[i]= i*i
}

return function (index) {
    console.log(a[index])
    }
}

const closure = find()
console.time("6"); 
closure(6); // this takes 0.25 ms
console.timeEnd("6");
console.time("12");
closure(12) // this takes 0.025ms
console.timeEnd("12");

6. What will be the output for the following?

for (var i = 0; i < 3; i++) {
  setTimeout(function log() {
    console.log(i); // What is logged?
  }, 1000);
}

**Solution : ** 333

7. How would you use a closure to create a private counter?

You can create a function within an outer function (a closure) that allows you to update a private variable but the variable wouldn't be accessible from outside the function without the use of a helper function.

function counter() {
  var _counter = 0;
    // return an object with several functions that allow you
    // to modify the private _counter variable
    return {
      add: function(increment) { _counter += increment; },
    retrieve: function() { return 'The counter is currently at: ' + _counter; 
        }
  }
}

// error if we try to access the private variable like below// _counter;// usage of our counter function
var c = counter();
c.add(5);
c.add(9);

// now we can access the private variable in the following way
c.retrieve();// => The counter is currently at: 14

8. What is module pattern?

var Module = (function() {
    function privateMethod() {
        // do something
    }

    return {
        publicMethod: function() {
            // can call privateMethod();
        }
    };
})();

The return statement of the Module contains our public functions. The private functions are just those that are not returned. Not returning functions makes them inaccessible outside of the Module namespace. But our public functions can access our private functions which make them handy for helper functions, AJAX calls, and other things.

Module.publicMethod(); // works
Module.privateMethod(); // Uncaught ReferenceError: privateMethod is not defined

One convention is to begin private functions with an underscore, and returning an anonymous object containing our public functions. This makes them easy to manage in a long object. This is how it looks:

var Module = (function () {
    function _privateMethod() {
        // do something
    }
    function publicMethod() {
        // do something
    }
    return {
        publicMethod: publicMethod,
    }
})();

9. Rewrite the function in such a way the output gets printed once even though the function is called multiple times.

let view
function likeTheVideo(){
    view="Roadside Coder"
    console.log( "Subscribe to", view)
}

likeTheVideo(); // Subscribe to Roadside Coder
likeTheVideo(); // Subscribe to Roadside Coder
likeTheVideo(); // Subscribe to Roadside Coder
likeTheVideo(); // Subscribe to Roadside Coder

Solution :

let view;
function likeTheVideo(){
    let called = 0;

    return function(){
        if(called>0){
            console.log("Already Subscribed");
        }
        else{
            view="Roadside Coder"
            called++;
            console.log( "Subscribe to", view)
        }
    }
}

let isSubscribe = likeTheVideo()

isSubscribe() // Subscribe to Roadside Coder
isSubscribe() // Already Subscribed

**10. Write the polyfill for "_.once" method in lodash. **

function once(func, context) {
  let ran;
  return function () {
    if (func) {
      ran = func.apply(context || this, arguments);
      func = null;
    }

    return ran;
  };
}

// Usage
const hello = once(() => console.log("hello"));

hello();
hello();

**11. Write the polyfill for "_.memoize" method in lodash. **

function memoize(func) {
  let res = {};

  return function (...args) {
    const argsIndex = JSON.stringify(args);
    if (!res[argsIndex]) 
             res[argsIndex] = func(...args);
    return res[argsIndex];
  };
}

const clumsysquare = memoize((num) => {
  for (let i = 1; i <= 100000000; i++) {}

  return num * 2;
});

console.time("First call");
console.log(clumsysquare(9467));
console.timeEnd("First call");

// use the same value two times
console.time("Second call");
console.log(clumsysquare(9467));
console.timeEnd("Second call");

Got any suggestions for the blog? Let's connect on Twitter.

Piyush Agarwal (RoadsideCoder)

Follow Roadside Coder on Youtube for more such great videos on JavaScript and React. Roadside Coder

Did you find this article valuable?

Support Roadside Coder by becoming a sponsor. Any amount is appreciated!