/ currying

Applying the Javascript's call and apply methods

Javascript’s call and apply methods are one of the most widely used and often misunderstood and underestimated functions in Javascript. Let’s explore them with a few patterns and common use cases. If you don’t have a clear understanding of the bind method and “this” keyword, I would recommend you go have a look at my earlier post here and here.

Apply allows us to invoke a function with an externally provided this reference and a set of arguments provided as an array/array-like-object.

func.apply(thisArg, [argsArray])

Looks pretty straightforward and dumb, but it has pretty wide usage patterns. Let’s have a look at a couple of those.

Borrowing functions

An interesting usage pattern in Javascript is to borrow functions from other objects and use it, rather than creating a new copy of the method and maintaining it twice. A lot of popular libraries we use rely on this pattern. Let’s look at an example.

In the snippet above, we have a counter “counter1” with a method to increment the counter value. If we would like to have a new counter similar to 1st and want to reuse/borrow the method already defined for “counter2″, we can call the apply method on the function with the “this” reference bound to counter2 and passing the arguments to be applied as an array. Results look like as follows.

Example result of borrowing a function

Using apply to inherit functions

The above example we saw was pretty much a one-time execution of the function. Let’ say we want to inherit the functions so that they can be called a number of times. Let’s look at the same example with the inheritance in place.

In the snippet above, the 2 counter objects are inheriting the global method and maintaining their own wrapped copy. Any changes to the global method will be reflected in the further execution of the counter increment methods.

Another interesting observation is that in the apply method, we are passing the “arguments” object as a second reference. Since the apply method can take the method arguments as an array or array-like object, we can pass the function arguments without any modifications to the downstream function call. If you have trouble understanding the “arguments” object, check out this documentation. The result looks as follows:

Example result of using the apply in inheritance use case.

What’s call

The above example brings us to another important distinction. Before jumping into the definition, let’s rewrite the same example with the “call” method. We are going to simply replace the use of the apply method with the call method. Here’s the example.

If you notice in the above snippet, the use of “apply” method is replaced with a use of “call” method. Also, unlike the “apply” method, the “call” method cannot take an array or an array like object as the argument, it requires explicitly specifying all the method arguments. Here’s how the results look like.

Example result of using call.

Defining the Call method

The call() method calls a function with an externally provided this reference and arguments provided individually.

The method can be expressed as follows

function.call(thisArg, arg1, arg2, ...)

Why apply when we have call

The call method was defined in the Javascript v1 and used internally while the apply method was initially defined and implemented in Javascript v3. But, why would we need a new method for similar functionality? Well, let’s look at an example.

In the snippet above, we have a similar method with a generic increment counter. But this counter can take on any number of arguments and add the count, or what is called a variadic function. We have used "apply" method to pass the arguments object to the parent generic method. Good luck implementing that with "call" . Here are the results.

Example result of using call.

Few more practical examples

Since we got an idea of what “apply” and “call” does, let’s look at a few more practical examples of the same.

Monkey-patching

Monkey patching is a common pattern used to extend the functionality of an existing method or system. Let’s consider an example of a function that finds out a maximum of a set of numbers. Now, we wanna make sure, that we log the function whenever it gets executed. So, we are gonna wrap the function in a new function with the additional logic of logging and monkey patching the original function. Here’s the example below:

In the above example, we are monkey patching the “addNewMax” function. The example lists the two approaches to accomplish that. We use the “apply” and the “call” method. Notice that, the call method can only take the arguments we supply to it and not any number of arguments.

Borrowing Native Methods

Javascript as a functional language offers functions as 1st class constructs and hence we can borrow methods literally from anywhere. Let’s see an example of borrowing some method from Arrays.

In the snippet above, we create an “array-like object” . An array like object has the values indexed by non-negative numbers and has a special length property. If we try to use the push method on the object, it will complain saying no such method exists. However, we can borrow the method from Array and call its method with a given “this” value and arguments. The result is as follows:

There are many more use cases like these and it’s hard o walk through each of these. let me know if you need to understand any particular use case, i will be happy to add.

Love Hasija

Love Hasija

Full Stack Research Engineer, Software Architect | Helped build next generation software systems | Distributed Systems Fanatic | Open Source Hacker.

Read More