javascript call - javascript call function

Changing Function Contexts with Javascript Call()

Calling functions in Javascript is usually straightforward: define a function, call it when you’re ready, and the function runs in the current context. This behavior has been part of programming languages forever.

Every once in a while, as this article will explain, you might want to explicitly change the context in which you call Javascript functions with the call() function.

This article explains what the call() function is, describes its use in modern Javascript, and then gives a brief overview of similar Javascript functions that developers sometimes confuse with Javascript call().

The Javascript Call() Function

The Javascript call() function allows developers to specify the context to call functions from by manipulating the value of the Javascript keyword this. (All parameters to the Javascript call() function are optional, but developers usually call it with at least one parameter).

Developers use Javascript’s strict mode for production code — in which any uninstantiated parameters to functions are set to be the undefined data type. Using the call() function without parameters leaves this undefined, making the call effectively useless in strict mode.

"use strict";
function hello() {
    console.log("Hello, I am ${this.first} ${this.last}.");
}
const me = {
    first: "Mortimer",
    last: "Fortesque"
};

hello.call();    // Hello, I am undefined undefined.
hello.call(me);  // Hello, I am Mortimer Fortesque.

The rest of the parameters to call() are parameters to be sent to the function being invoked. Expanding on the above example (and assuming the same context as above with the me object), if one could specify the greeting in the hello() function as a parameter, the call would look like this:

"use strict";
function hello(greeting) {
    console.log(greeting + " ${this.first} ${this.last}.");
}

hello.call(me, "My name is");  // My name is Mortimer Fortesque

This example is okay for demonstrative purposes, but looking at it more closely raises an important question: why bother changing the context of a function when you could simply pass parameters to the function? A simple restructuring of the function above would be equivalent to using call():

"use strict";
function hello(greeting, first, last) {
    console.log(greeting + " " first + " " + last + ".");
}

hello("My name is", "Mortimer", "Fortesque");
// My name is Mortimer Fortesque.

It’s easy to assume, if you only see examples like this, that the Javascript call() function is just a roundabout way to do something that functions or other modern Javascript constructs do better. Before Javascript ES6, for example, call() was the only reliable way to mimic inheritance, and the later development of Javascript classes made that use case unnecessary.

Javascript Call() in Callbacks

There is one use case where call() remains relevant in modern Javascript; when handling execution context in function callbacks.

If you pass a callback to another function, the execution context of that callback (denoted by the this keyword) is the function that contains the callback. In this example, the context of the anonymous callback is the setTimeout() function.

function timer() {
    let count = 0;
    setTimeout(function() {  
        console.log("This message is shown after 3 seconds");
        this.count++;
        console.log("Function called " + this.count + " time(s)");
    }, 3000);
}

// This message is shown after 3 seconds
// Function called undefined times

The setTimeout() function in this example does not contain a variable count, so this.count is undefined. To use count, we must connect the callback to its appropriate context: the timer() function.

function timer() {
    let count = 0;
    setTimeout(function() {  
        console.log("This message is shown after 3 seconds");
        this.count++;
        console.log("Function called " + this.count + " time(s)");
    }.call(this), 3000);
}

// This message is shown after 3 seconds
// Function called 1 time(s)

Since this has multiple contexts in close proximity, a good practice is to separate the callback from its calling function to further distinguish between the contexts for maintenance purposes.

function callback() {  
    console.log("This message is shown after 3 seconds");
    ${this.count}++;
    console.log("Function called " + this.count + " time(s)");
}

function timer() {
    let count = 0;
    setTimeout(callback.call(this), 3000);
}

// This message is shown after 3 seconds
// Function called 1 time(s)

Similar Functions to Javascript Call()

The Javascript call() function is one of three that manipulate execution context by explicitly setting the value of this. The other two are bind() and apply().

call() is best used for functions that require a specific this value, must be called immediately, and are called only once. This makes it useful for single calls to setTimeout() and similar applications.

bind() takes the same parameters as does call(), in the same order, but is not executed immediately and can be executed more than once. This makes it useful for maintaining context in event listeners, such as when monitoring a button click.

function callback(message2, message3) {
    console.log(${this.message} + message2 + message3);
}

function addListener() {
    let message = "button clicked";
    button.addEventListener('click', callback.bind(this, "a", "b"));
}

apply() works identically to bind(), except that it takes only two parameters: the explicit value for this and callback parameter functions as an array.

function callback(message2, message3) {
    console.log(${this.message} + message2 + message3);
}

function addListener() {
    let message = "button clicked";
    button.addEventListener('click', callback.apply(this, ["a", "b"]));
}

Conclusion

The Javascript call() function and the related functions bind() and apply() are rarely used in modern Javascript code because many of their previous functions have been made obsolete. Javascript call() has an enduring role in handling function callbacks, and is still found in some major Javascript frameworks, such as React. bind() and apply() continue to be used to solve specific needs.

Start Learning

To learn more about Javascript, check out other Javascript blog posts and enroll in our Javascript Nanodegree programs, including Intermediate Javascript.