Introduction

Function are a bunch of useful constructs in JavaScript, and all other programming languages, to aid in representing repetitive code blocks as one single entity that can be invoked again and again, at will.

However this feature is common to functions in all programming languages, and isn't the thing that will surprise us in terms of functions in JavaScript. Rather what's superbly interesting, yet powerful, in this language is the fact that functions are also objects and have properties as well as methods available on them.

In this chapter we shall explore the three most frequently used methods inherited by all functions i.e bind(), call() and apply().

Bound functions

Functions are engaging - bound functions are even more! Let's see what they are.

A bound function wraps an ordinary JavaScript function with a given value of this, along with the given arguments.

Didn't understand a word? Don't worry; you'll understand this definition clearly only once you understand how to create a bound function and get to know what specific purpose it serves.

Let's start from scratch.

Normally, when the JavaScript runtime calls any function, it passes it a value of this that is the object on which the function is called.

For example in the code below sayHello() is called directly (which is taken to be on window) and thus has this pointing to window.

function sayHello() {
    console.log(this); // window
}

sayHello();

Similarly in the code below, sayHello() is called on the object person, and thus has this pointing to person:

var person = {};
person.sayHello: function() {
    console.log(this); // person
}

person.sayHello();

The idea is simple, this depends on the object on which a function is called, at runtime; NOT on the object on which it is declared.

However, this normal functionality can be changed using the method bind(). It can get a function to take any value of this we like.

The first argument of the method bind() is the value this will be given inside the function, while the subsequent arguments are provided to the function itself (as its own arguments), upon invocation.

On completion, bind() returns what we call a bound function.

This returned function has four internal properties according to the ECMAScript spec, that makes it be recognised as a bound function:

  1. [[BoundTargetFunction]] - the function on which bind() was called.
  2. [[BoundArguments]] - holds the set of arguments passed to bind(), starting from its second argument.
  3. [[BoundThis]] - the value of this passed to bind().
  4. [[Call]] - the method to execute the bound function.

When a bound function is called, the interpreter executes the underlying internal [[Call]] property, which in turn invokes the function saved in [[BoundTargetFunction]] by providing it with arguments [[BoundArguments]] and [[BoundThis]] as a value for this.

These internal properties are what make a bound function operate as one.

Akin to normal functions, a bound function also has a [[Call]] internal slot, but this behaves slightly differently than the one on normal functions, in that the value for this is NOT set to the calling context, but rather to [[BoundThis]].

Since bound functions have a slightly different internal behaviour than normal functions, they are termed as exotic objects.

Let's consider a quick example:

var name = "Global name";

function alertName() {
    alert(this.name);
}

alertName(); // "Global name"


var obj = {name: "Object name"};
var alertName2 = alertName.bind(obj);

alertName2(); // "Object name"

First we create a variable name (which is also available as window.name) and then a function alertName() to alert the value of this.name. Calling this function directly in line 6, resolves its this value to window and likewise we get "Global name" alerted.

After this we create an object obj and under it, another name property. Finally we create a function alertName2(), using bind(), which means that it is just a bound function for alertName().

The this value we bind to alertName() in the code above is obj and so calling the bound function alertName2(), in line 13, will refer to the name property on obj and thus alert "Object name".

Following is another example:

var logger = {
    x: 10,
    log: function() { console.log(this.x); }
};

setTimeout(logger.log, 3000);

Here we have an object logger and its methods log() to make a console log after 3 seconds, printing the value of the property x.

Typically, developers forget the fact that passing an object's method to setTimeout() will result in its this value resoving to window, rather than the object on which it was defined; as it's window.setTimeout() whose calling the method, not the object.

This means that in the code above, once setTimeout() fires, we will get undefined log, as there's NO property x on this (which is equal to window).

undefined

A usual solution to this, at least in this case, is to refer to the object logger directly in the log() method (by logger.x) instead of getting this.x. Typically one would write the following code to mitigate this problem:

var logger = {
    x: 10,
    log: function() {
        var self = logger;
        console.log(self.x);
    }
};

setTimeout(logger.log, 3000);

This works well, but not without handcrafted code - we have to manually refer to logger inside the definition for the method log(), and if for some reason its name changes, we'll have to also make the change here.

Although this is not difficult to do, it is senseless. Ideally all methods of a given object shall refer to the object using this - these methods are defined on it and hence technically already know it!

A convenient and extremely straightforward solution to this is to bind a value of this with the method and create a bound function out of it.

Consider the modified code below:

var logger = {
    x: 10,
    log: function() { console.log(this.x); }
};

setTimeout(logger.log.bind(logger), 3000);
10

Now our code is a lot more compact, and at the same time a little more flexible; all methods of logger now refer to it using this only, and not the object's identifier itself.

Adding arguments

Uptil now we've covered nearly all aspects of bind(), except for argumented functions.

As said before, arguments to the actual function start from the second argument of the bind() method - the first argument being preserved for a prescribed value of this, as we've seen above. These arguments are put into the [[BoundArguments]] internal slot and then re-read once the bound function is called.

In other words, all arguments passed to the bound function, while it is invoked, are appended to the list [[BoundArguments]] and then passed over inside the function.

Following is an illustration:

Methods

apply()

The apply() method works exactly similar to call() apart from that it provides the calling function with its arguments in array form. Notice the word array over here.

function apply(a, b) {
    return this.x + this.y + a + b;
}
var x = y = 5;
add(5, 5); // returns 20 (5 + 5 + 5 + 5)

var obj = {x: 5, y: 15};
add.apply(obj, [5, 5]); // returns 30 (5 + 15 + 5 + 5)

This method can be used to easily find the maximum or minimum value in an array. Although this task can be accomplished using a for loop too, it would however be way longer than the simple code using apply():

var arr = [1, 8, -2, 20];
Math.min.apply(undefined, arr) // returns 20

The method Math.min() returns the maximum value from the provided number of arguments. The arguments MUST be in aparametric form like a, b, c, d, e..... An array CAN'T be sent to the method Math.min() expecting it to return its element with the max value.

And because of this we employ the method apply() to supply it with given arguments that are the elements on an array.

Calling with this

Apart from binding a given value of this with a function, it's also common, in fact even more common, to right away call it with the provided this. The method call() just serves this purpose.

call() invokes its calling function with a given value of this, in its first argument, and along with that arguments for the function itself.

Consider the code below, where we have a function incrementCounter() to increment the property counter of a given object by a desired value:

function incrementCounter(num) {
    this.counter += num;
}

Following we use this function to alter counter on some objects, by assigning it to a property of each object. This is done so that this resolves to the object, and not to the global window context.

var obj = {
    counter: 10,
    incrementCounter: incrementCounter
};

obj.incrementCounter(5);
console.log(obj.counter); // 15


var obj2 = {
    counter: 0,
    incrementCounter: incrementCounter
};

obj2.incrementCounter(10);
console.log(obj2.counter); // 10

obj2.incrementCounter(3);
console.log(obj2.counter); // 13

As you might realise, this is fairly inefficient - we are merely reassigning the function again and again and creating useless properties on all the objects.

The question is that is there a simpler solution? And you guessed it - simply use call()!

var obj = {
    counter: 10
};

incrementCounter.call(obj, 5);
console.log(obj.counter); // 15


var obj2 = {
    counter: 0
};

incrementCounter.call(obj2, 10);
console.log(obj2.counter); // 10

incrementCounter.call(obj2, 3);
console.log(obj2.counter); // 13

Focusing on line 5, the first argument to call() is obj - which means that this will be equal to obj within the definition of incrementCounter(). After this, the second argument is 5 - it will be passed to incrementCounter(), which will then increment counter by 5.

Same stuff happens on lines 13 and 16, this time on obj2.

Remember that the actual arguments of a function are provided to call(), starting from the second argument. The first one is reserved for assigning a value to this, the rest are arguments to the function itself!

Simple examples work well, but let's now consider a practical usage of call().

Array-like to an array

Suppose we need a function transform() to transform an array-like object into an actual array to enable array methods like sort(), and slice() on it.

For example take the arguments object available to all functions - it is an array-like indexed collection of the arguments passed to the function; NOT an actual array.

To sort out this problem we can either craft a slicing algorithm on our own, from scratch, or use a rather clever technique.

The technique is to invoke slice() on Array.prototype, using its method call() and pass it the array-like object as the this value.

What will happen as a consequence is that slice() will be called on the array-like object, and thus loop over its entire indexed collection, pushing each individual element onto a fresh, new array and finally return this array.

Following is a demonstration:

function transform(arrayLikeObj) {
    return Array.prototype.slice.call(arrayLikeObj);
}

arrayLikeObj is the array-like object we wish to transform into a native array, and the argument to the method call(). Recall that the first argument of call() is the value for this; which means that within slice()'s definition this will be equal to arrayLikeObj.

It'll all sound sensible with an example:

function is5Present() {
    return transform(arguments).indexOf(5) !== -1
}

console.log(is5Present(1, 2, 3)); // false
console.log(is5Present(1, 5, 3)); // true
console.log(is5Present(-5, 10, 55)); // false
You'll understand more about the prototype property in the JavaScript Object Prototypes chapter.
Do you know how Array.prototype.slice() works? It's the same slice() method we call directly on arrays. It simply loops over all the indexed keys in this upto the collection's length, and appends them to a newly created array.

Emulating subclass behavior

Perhaps a real practical significance of the method call() is in emulating the behaviour of a subclass inheriting from a parent class in JavaScript using constructor functions.

The idea is that we pass the this object of a subclass constructor to the constructor for the parent class and ultimately call it. This enables both the constructors to be executed with one single this value.

We'll explore more details to this application of call() in the JavaScript Object Constructors chapter.

In conclusion

And that's it for function methods and even for this whole functions unit. You've learned a lot of stuff uptil now, have gained a solid ground in various concepts of JavaScript functions and now is the high time to test out your skills in a relatively difficult quiz.

When you're feel you're rock solid on functions press the next button. We'll see you in the functions quiz!