Lexical Scope, Closures and Currying in JavaScript Lexical Scope, Closures and Currying in JavaScript

This post describes the Lexical Scope, Closures and Currying Function in JavaScript and their relations with examples.

Lexical Scope


Variables defined using var keywords are having function scope which means new scope is created everytime you create a new function.

Lexical scope is associated with function scope. Lexical scope of variables is defined by their position in source code. JavaScript resolves the variable starting at the innermost scope and searches outwards until it finds the variable it was looking for.

var me = "global";
function whoami(){
    var me = "local";
    function func() {
        return me;
    }
    return func;
}
console.log(me);          // global
console.log(whoami()());  // local

The value of the variable me outside is global whereas if you execute function whoami() from outside, value is local

Closures


Closure is very important concept and frequently asked in JavaScript interviews.

A closure is an inner function having access to its outer function scope and all above scopes even when that function is executing outside of its outer function.

When you define an inner function inside outer function, Closure is created at runtime for inner function bundled with outer function’s scope.

Let’s look at the example to understand Closures

var outerFunc  = function(c){ 
   var a = 1;
   var innerFunc = function(d) {
	  var b = 2;
      var innerMostFunc = function(e) {
		return a + b + c + d + e;
	  }
	  return innerMostFunc;
   }
   return innerFunc;
}
console.dir(outerFunc(3));        //1. innerFunc
console.dir(outerFunc(3)(4));     //2. innerMostFunc
console.log(outerFunc(3)(4)(5));  //3. 15
Output
▼ ƒ innerFunc(c) length: 1 name: "innerFunc" arguments: null caller: null ➤ prototype: {constructor: ƒ} ➤ __proto__: ƒ () [[FunctionLocation]]: ▼ [[Scopes]]: Scopes[2] ➤ 0: Closure (outerFunc) {c: 3, a: 1} ➤ 1: Global {parent: Window, opener: null, top: Window, length: 1, frames: Window, …} ▼ ƒ innerMostFunc(c) length: 1 name: "innerMostFunc" arguments: null caller: null ➤ prototype: {constructor: ƒ} ➤ __proto__: ƒ () [[FunctionLocation]]: ▼ [[Scopes]]: Scopes[3] ➤ 0: Closure (innerFunc) {d: 4, b: 2} ➤ 1: Closure (outerFunc) {c: 3, a: 1} ➤ 2: Global {parent: Window, opener: null, top: Window, length: 1, frames: Window, …} 15

We have three console dir/log. Let’s discuss them one by one:

  1. innerFunc has a closure of variables defined or passed as argument in outerFunc

     0: Closure (outerFunc) {c: 3, a: 1}
    
  2. innerMostFunc has a closure of variables defined or passed as argument in in outerFunc and innerFunc i.e.

     0: Closure (innerFunc) {d: 4, b: 2}
     1: Closure (outerFunc) {c: 3, a: 1}
    
  3. innerMostFunc returns a+b+c+d+e=15 where

    • value of a and c is coming from Closure (outerFunc)
    • value of b and d is coming from Closure (innerFunc)
    • value of e is coming from passed argument

They way we called outerFunc(3)(4)(5) is also known as currying

Currying


One of the use case of Closure is currying functions.

A currying function is a function where you break down a function that takes multiple argument one at a time instead of taking all argument at once.

f(a, b, c) => Currying => f(a)(b)(c)

Let’s convert this function

var add = function(a, b, c){
    return a + b + c;
}

add(1, 2, 3); //6

to currying function

var add = function(a){
    return function(b){
        return function(c){
            return a + b + c;
        }
    }
}
add(1)(2)(3); //6

One more example:-

var sayWhat = function(a){
    return function(b){
        return function(c){
            console.log(`say ${a} to ${b} using ${c}`);
        }
    }
}

sayWhat("hello")("friends")("currying function");
Output
say hello to friends using currying function

In currying function, each nested function is keeping track of arguments passed in outer function in their closure,