Call Apply And Bind

Today we've got a post about some useful methods every JavaScript function has: call, apply, and bind.

Yep, that wasn't a typo, in JavaScript all functions are objects and they all have methods. Kinda weird I know. :)

Here's a function:

var greeting = function () {  
    return `Hi, I'm ${this.name} ` +
           `I like ${this.favorite_food}`
}

If we simply call this function, we'll get

Hi, I'm undefined I like undefined  

But if I define an object with a name and favorite_food and call it bobby, I can do this:

greeting.call(bobby)  

This returns

Hi, I'm bobby I like pizza  

greeting is a function. call is a method that calls a version of greeting, but with its this set to the first argument of call.

This is how I defined bobby:

var bobby = {  
    name: 'bobby',
    favorite_food: 'pizza',
    inventory: ['pizza', 'ice cream', 'banana'],
    willing_to_trade: {
        'ice cream': 'apple pie',
        'banana': 'apple'
    }
}

bobby has pizza, ice cream, and a banana. They're willing to trade ice cream for apple pie, and a banana for an apple.

Here's a function reflecting this:

var will_trade = function (give, take) {  
    return has(give, this.inventory)
        && this.willing_to_trade[give] === take
}

If I want, I can use call to set will_trade's this value to bobby:

will_trade.call(bobby, 'banana', 'apple')  

This returns true.

I can also use apply:

will_trade.apply(bobby, ['ice cream', 'apple pie'])  

which also gives me true

apply is just like call, but instead of taking a list of comma separated arguments, it takes an array of arguments instead.

apply can be useful if, for example, you want to build or modify an array and then call a function with that array as its arguments.

I can also use bind to add a method to bobby:

bobby.will_trade = will_trade.bind(bobby)  

Now I can do this:

bobby.will_trade('banana', 'apple')  
bobby.will_trade('candy bar', 'apple')  

These return true and false respectively.

bind returns a function like the original, but with its this value set to bind's first parameter.

You can also use bind to curry:

var bobby_will_trade_banana_for =  
    will_trade.bind(bobby, 'banana')

and use the function like so:

bobby_will_trade_banana_for('apple')  
bobby_will_trade_banana_for('soap dish')  

These return true and false respectively.

Of course, you don't have to give a proper value for this to any of these functions to make them useful:

var add_4 = (a, b, c, d) => a + b + c + d  
var add_2 = add_4.bind(undefined, 0, 0)

console.log(add_4.call(undefined, 1, 2, 3, 4))  
console.log(add_4.apply(undefined, [1, 2, 3, 4]))  
console.log(add_2(1, 2))  

This prints:

10  
10  
3  

Looking for a software developer?