Introduction to the Introduction of Functional Programming in JavaScript

The story of Apply, Call & Bind

Posted by Anas R Firdousi on March 24th, 2016
25 mins read

Before we discuss what's Functional Programming and why JavaScript is a powerful tool to help you go functional, it is important to understand JavaScript functions. Over a decade, I have had the chance to work with beginners(like myself), professionals and JavaScript experts. A common misconception I found was people want to look at functions in JavaScript as they look at function in Java/C# or other famous programming languages.

Functions Are Objects in JavaScript

Objects can have state(properties) and behavior(methods)

In JavaScript, you can create objects in a number of ways. These objects contain properties and functions. Functions themselves are objects. And as an object, functions have their own methods. The only difference function objects and normal objects is that function objects can not share state among its methods.

So functions in JavaScript have methods of their own. Let's quickly look at a JavaScript object.

        

        var Employee = {

          name:"John Doe",
          age:100, // Log to console by default

          setName:function(name){
            this.name = name;
          },

          setAge:function(age){
            this.age = age;
          },
      
          showDetails:function(){
            console.log("Employee Details:");
            console.log(this.name,this.age);
          }

        }

        
      

The Employee object here has state (name & age), and a "showDetails" function. This "showDetails" function itself is an object. Every type in JavaScript is essentially drived from "Object" type. Since "showDetails" function is an object, it has methods of its own and some methods that it inherits from its base object "Object".

Since JavaScript has prototypal inheritance, Object inherit from other base Objects and extend them i.e. add properties to them.

  • Methods that functions inherit from "Object" base are toString(), toLocaleString() e.t.c.
  • Methods that are function's own methods are Apply, Call, Bind (and some others).

Apply and Call can be used to set the environment in which a function runs, in other words, they are used to set the value of "this" explicitly. Apply can also be used for "Variable-arity", a concept we will learn later in this post. Bind can be used effectively for "currying" functions and we'll discuss that in this post as well.

Call & Apply were there in JavaScript since forever (1999 - ECMA3). Bind is relatively new, was added to ECMA5(2009).

Let's look at a simple jQuery click handler,


        

          $("#btnShowDetail").click(Employee.showDetails);

        

      

The meaning of "this" depends on the context(the environment) it is wrapped in.Yes, you guessed it right, "this" here refers to the button and not the "employee" object we previously wrote. The above code will fail.

  • 'this' is accessed within an anonymous function and anonymous function here is running in the context of click handler.
  • 'this' has no value when defined inside an anonymous function and anonymous functions do not have access to 'this' variable defined in the outer function.
  • BUT jQuery binds 'this' to the object that invokes the click handler.
  • If you add this line within the click handler
    console.log(this)
    you will get
    [Button object]

Bind() To Change The Meaning of "this"

So if we want to read "name" and "age" of our employee in the above click handler, we have to use the BIND method of the function object and change the meaning of 'this' within our click handler.


      
          $("#btnShowDetail").click(Employee.showDetails.bind(Employee));
      


    

If you want to run code in older browsers (like IE < 9, Firefox < 4, Chrome < 7, Safari < 5.1), you need to include the Bind() implementation. Find it here


        

            if (!Function.prototype.bind) {
              Function.prototype.bind = function(oThis) {
                if (typeof this !== 'function') {
                  // closest thing possible to the ECMAScript 5
                  // internal IsCallable function
                  throw new TypeError('Function.prototype.bind - 
                   what is trying to be bound is not callable');
                }

                var aArgs   = Array.prototype.slice.call(arguments, 1),
                    fToBind = this,
                    fNOP    = function() {},
                    fBound  = function() {
                      return fToBind.apply(this instanceof fNOP
                             ? this
                             : oThis,
                             aArgs.concat(Array.prototype.slice.call(arguments)));
                    };

                if (this.prototype) {
                  // Function.prototype doesn't have a prototype property
                  fNOP.prototype = this.prototype; 
                }
                fBound.prototype = new fNOP();

                return fBound;
              };
            }

          

      

As we discussed, in JavaScript functions are first-class objects, which have properties and methods. Functions can also be passed around as arguments to other functions and can also be assigned to variables. Let's assign it to a variable.


        

            var anotherShowDetails = Employee.showDetails;
            anotherShowDetails();

        

      

Calling anotherShowDetails() will be problematic again for the same reason and the fix is exactly the same.


        

            var anotherShowDetails = Employee.showDetails.bind(Employee);
            anotherShowDetails();

        

      

Bind() to Borrow Methods from Other Objects

Consider the following Student object,

          

              var Student = {

                  profile:{
                    name:"Kane Wilson",
                    age:70
                  }

              }

          
      

This Student object can borrow showDetails() method from the Employee object. Let's do it:

          

              Student.showDetails = Employee.showDetails.bind(Student.profile);
              Student.showDetails();

          
      

Bind() to Curry a Function

Suppose there is a function that accepts 2 arguments. In JavaScript, you can call this function just by passing 1 argument and create a new function which accepts another argument. This partial function application is called Currying. Let's look at a quick example:

          

          //A function that adds 2 numbers
          function add(n1,n2){

            return n1+n2;

          }

          //Calling with passing few arguments to create a 
          //partial function implementation
          
          var adder2 = add(2);  // 'adder2' is a partial application of 'add'

          //  Internally, adder2 looks like this
          //
          //  {
          //    return 2 + n2;
          //  }

          console.log(  adder2(30) );   // 32
          

        

Now let's look at how we can use 'Bind()' to Curry our functions.

        

            //This is a log() function

            function log(level,severity,msg){

                var lev = "",sev="";

                if(level<2){
                    lev = "MINOR";
                } else if(level===2){
                  lev = "MAJOR";
                }else{
                  lev= "CRITICAL";
                }

                if(severity<=5){
                  sev = "LOW";
                }else{
                  sev = "HIGH";
                }

                return [lev," : ",sev," : ",msg].join('');

             }

            //Let's Curry up this function in few ways

            //Example#1
            var logCritical = log.bind(null,"CRITICAL");

            //Example#2
            var logCriticalHigh = log.bind(null,"CRITICAL","HIGH");

            //Let's use above:

            console.log(logCritical("LOW","Email notification exception"));
            console.log(logCriticalHigh("Resource not found exception"));


        
      

In both example#1 & example#2, we are passing "null" as first arguments to bind. Why? Because we don't want to explicitly set the value of 'this' in this case because we are not using 'this' anywhere within our log() function so we don't need to pass anything to bind's first argument which is used to explicitly change the meaning of 'this'. The actual arguments to log() start from the 2nd argument. In example#1, we pass only "level" argument to the log function. In example#2, we pass both "level" as well as "severity" to the log function and leave the last "msg" argument to be applied when the curried implementation is called.

While currying a function, you can pass in any number of original arguments and leave any number of arguments to be passed to the curried implementation.

Using Apply and Call Method

You may have seen expert JavaScript developers often make use of Apply() and Call() function. We will try to demystify that now. We can do the following with Appl() and Call().

  • Like Bind, Apply & Call can be used to explicitly set the value of "this" in function invocation.
  • Like Bind, Apply & Call can be used by JavaScript objects to borrow functions from other objects.
  • Apply can also be used to execute a function with an array of parameters, such that each argument is passed to the function individually(one by one) as they execute. The number of items in this passed array can be variable. This is a good base to create functions with "Variable-arity".
In computer programming, a variadic function is a function of indefinite arity, i.e., one which accepts a variable number of arguments. Support for variadic functions differs widely among programming languages.
To read more about Variable-arity, check out this Wikipedia page

Apply()/Call() To Change The Meaning of "this"

Since we have done this before with Bind, we will go through this fairly quickly. As was in Bind, the first argument of Apply/Call is used to set the value of 'this' to the object the function is invoked upon.

      
        
          var started = false;

          var Event = {
              device:"Apache Server 1",
              started:false
          }

          function StartEvent(){
                this.started = true;
          }

          StartEvent();

          console.log(Event.device + " is " + (Event.started?" running": " not running"));
          //Apache Server 1 is not running

          //Let's test the global "started" variable too 
          console.log(true);

          //What? 

          //Didn't we call StartEvent() ? Yes we did
          // But StartEvent() set's up the global "started" variable. It does set's up the Event's "started" variable

          //To fix this, let's first reset the global "started" variable to false
          started = false;

          //Then use the Call() function to set Event Object's "started" variable.

          StartEvent.call(Event);
          console.log(Event.device + " is " + (Event.started?" running": " not running"));
          //Apache Server 1 is running



        

      

The first argument to call() set's the value of 'this' within the context of StartDevice() function.

Is there any difference between Apply & Call ?

The apply and call method are almost the same. The only noticeable difference is you pass the function parameters to Apply as an Array , like, functionName.apply(,[]) while in Call we have to list the parameters individually.
We already saw how to use Call(), and Apply() can be applied in exactly the same way except for the fact that if we have to pass any arguments , after specifying the first "this" argument, we have to pass all those arguments from 2nd parameter onwards in an Array. We will see examples for Apply shortly.

We can also use Apply()/Call() in a callback function. You can ready about callback functions here.
When we write frameworks, we often want to provide lifecycle hooks to our framework consumer so that they can hook their methods before we run our methods within the framework. The following example is in no way closer to or as sophisticated as lifecycle hooks in frameworks like Angular/React, but I am just trying to give you a closer-to-real-world example.

        

            var started = false;

            var Event1 = {
                device:"Apache Server",
                started:false,
                count:0,
                msg:""
            }

            var Event2 = {
                device:"Windows Server",
                started:false,
                count:0,
                msg:""
            }

            function StartEvent(count,msg,callback,callBackThis){

                  callback.apply(callBackThis,[count,msg]);
                  this.started = true;
            }

            //Let's consume StarEvent function and pass it our hook.
            //Our hook will run before the device the device is started
            //i.e before this.started = true get's called.

            StartEvent(100,"Wohooo!!!",myCrazyHook,Event1);


            function myCrazyHook(count,msg){

                console.log("Hello from my Crazy Hook : Incrementing count");
                this.count++;
                //console.log(msg + " with a new count" + this.count);

            }

         
      

As we can see, Apply() method sets "this" to "callBackThis". This way, we are able to use the callback giving it an environment to run in.

Apply()/Call() to Borrow Methods from Other Objects

Like Bind(), the most common use from Apply/Call in JavaScript is to borrow functions from other objects.

If you, as a JavaScript learner, have seen developers write stuff like:

          
          
              Array.prototype.slice.call();
          

        
or stuff like
          
          
              myString.split("").reverse().join("");
          

        
and you found yourself scratching your head, be happy , as well demystify all of this up next.

Borrowing Methods From Array Class

JavaScript ships with powerful builtin methods. You can do concat(), map(), filter() ,reduce(), slice(), shift(),sort() and a lot more builtin Array methods.
General Objects on the other hand do not have do not have these many useful methods. The good news is, if your object is "Array-like" you can borrow methods from Array type and use it on your objects. To know more about "Array-like" object, you can read Dr.Axel's post here.

An array-like object is an object that has its keys defined as non-negative integers

Let's look at a very basic example to understand this "Array-like" object:

        

              function startRunning(){

                console.log("Starting to run...");

                console.log("In my bag I have ",arguments);

                console.log("Running...")

              }

              startRunning(1,2,3,4);

              //Output:

              //Starting to run...
              //In my bag I have  { '0': 1, '1': 2, '2': 3, '3': 4 }
              //Running...
          
        
      

Whether you have arguments defined on function body or not, every JavaScript always has this magical "arguments" object. As seen in this example, it is allowed to pass as many arguments as possible to a JavaScript function irrespective of the function definition. The magical "arguments" object is an "Array-like" object. It has non-negative integral keys with a value attached to each key. Key are in sequence starting from 0 which actually corresponds to the sequence in which you supplied arguments while calling the function. There are 2 important things to notice:

  • "arguments" object have length property defined on them, which is great.
  • You can iterate over "arguments" via "for" loop because it has keys defined for each index but you cannot loop over an "argument" i.e over an Array-like" objects forEach loop. The following code won't work:
  • forEach is an iterator over any iterable. Array is an iterable but "Array-like" objects are not pure iterable.
                
                    
                    function sayHello(){
    
                      //Code will break on the following line:
                      arguments.forEach(function(v){
    
                          console.log(v);
    
                      });
    
                    }
    
                    sayHello(4,5,6);
    
    
                
              

This was a short trip to "Array-like" objects. The point is we can use all builtin powerful Array methods on "Array-like" objects by borrowing Array methods.

"Array-like" objects are not necessarily "arguments" object that is magically defined within a function. We can also create our own "Array-like" objects. For example:
var myArrayLikeObject = {0:"Test Result",1:"Critical",2:"This is a major exception"};

For our example, we will be using "arguments" object and make it use all powerful Array methods. Let's borrow a few:

        
            function sayHello(){

                var args = Array.prototype.slice.call(arguments,0);

                console.log("Hello: Following values were passed:");
                args.forEach(function(v){
                    console.log(v);
                });

            }
        
      

Slice returns a portion of an Array as a new Array. We pass the index from where to start untill the end of Array, create a new Array out of this selected portion and return it. If we pass 0, this means we want pick all elements form start till end. If you have never used Array's slice function before, please read it here.

Congratulations! We can now iterate over "Array-like" objects as well by borrowing a method "slice" from Array methods and making using of our "Call()" function. The first argument we pass to Call is the object that sets the value of "this", as discussed before. Here we are passing the "arguments" object which will be the context (the "this") for slice. We can also borrow other useful Array methods like push, push and what not.

We can also borrow methods from String object and other objects in JavaScript. Since "String" is an immutable data type (learn about immutability here), only immutable arrays work on them (Ohh what? I will talk about this in another post, soon!) so you may not be able to use String methods which are not pure and make changes to the data structure like reverse, pop and others.

It's great to know that we can borrow methods from builtin objects/types like String and Array and also from our own custom objects as we saw earlier in this post.

Borrowed methods reflect original methods!

This is an important concept.For example, if you have a method A in type X, and type Y borrows method 'A' of type 'X' and starts using it. If type 'X' makes a change in the original method 'A', the change will definitely reflect in the borrowed version of 'A' in type 'Y'.

Variadic Procedures in JavaScript

In logic, mathematics, and computer science, the arity of a function or operation is the number of arguments or operands that the function takes. A function accepting a variable number of arguments is called variadic. In logic and philosophy, predicates or relations accepting a variable number of arguments are called multigrade, anadic, or variably polyadic
Let's take a quick example. There is a builtin "Math" object in JavaScript and Max & Min methods on the Math object are famous examples of variadic functions.
          
              
            var maxNum = Math.max(10,2,3,40,5,6,7,18);
            console.log(maxNum); //40

            var minNum = Math.min(10,2,3,40,5,6,7,18);
            console.log(minNum); //2

          
        

Similarly, we have a function called "reduce" over Arrays in JavaScript. We will discuss that in great detail in upcoming Functional Programmings posts but just give you a taste of it, let's write a variadic function called Sum(). The user should be able to pass any number of arguments and the function Sum() returns the result of addition of all those numbers.

          

      function Sum(){

            var args = Array.prototype.slice.apply(arguments);
            // You can use call() as well ^^


          var result = args.reduce(function(previousValue, currentValue, currentIndex, array) {
            return previousValue + currentValue;
          }, 0);

            return result;    


      }

      console.log(Sum(1,2));
      //3

      console.log(Sum(1,2,3,4,5));
      //15

          
        

This is great. We just wrote a Variadic again with the help of call & apply and this time with the powerful reduce function of Array type.

Let's end this post with a quick discussion of Min/Max. Min and Max function accepts a number of argument but individual arguments. They do no accept an Array to be passed to them. Can we use Apply() to ask Max/Min to accept and Array ? Let's try this out:

        
          
         //This does not work: 
         var numSet = [1,2,3];
         console.log (Math.min(numSet)); // NaN

         //This will:
         var numSet = [1,2,3];
         console.log (Math.min.apply(null,numSet)); // 1


        
      

This is the scenario where you can only use Apply() and cannot make use of Call() or Bind(). Why? Because Apply() is the only function that accepts an Array out of the 3 functions we have been talking about.

Oh wait, didn't we say "Functional Programming" ? Yes, this was an introduction to the introduction, something like a prelude before we get into Functional programming in our next writeup.

Feel free to leave a comment, question, suggestion.
Until next time, Happy learning!