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.
Looks pretty straightforward and dumb, but it has pretty wide usage patterns. Let’s have a look at a couple of those.
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.
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:
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.
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
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.
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 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
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.