If you spent enough time reading Javascript codes, you probably saw call
and apply
. If you are like me, you get confused real fast. Don't worry, these methods are pretty easy to understand. I will cover some of the basics to get you all started!
I will go over:
- How to use call
- How to use apply
- When to use call and when to use apply
Before we start, keep in mind that these two are very similar. Learning one allows us to understand the other.
Using call
Suppose we have an object and a function:
const breakfastObj = {
food: 'blueberry waffles',
drink: 'orange juice'
}
function sayBreakfast(){
console.log(`I had ${this.food} and ${this.drink} for breakfast`)
}
When we call sayBreakfast()
, it will return
sayBreakfast() // I had undefined and undefined for breakfast
To "call" the function sayBreakfast()
with breakfastObj
as this
:
sayBreakfast.call(breakfastObj) // I had blueberry waffles and orange juice for breakfast
Recall that this
, if not defined, refers to global object (if you are on browser, your global object is probably window
object). So we can do this:
window.food = 'French toast'
window.drink = 'Apple juice'
sayBreakfast() // ... French toast and Apple juice
This is equivalent to:
sayBreakfast.call() // ... French toast and Apple juice
Call also accepts 2nd, 3rd, ...nth arguments. These arguments are used as function's arguments. Let's look at example to clarify:
const lunchObj = {
food: 'tacos',
drink: 'water'
}
function sayLunch(location){
console.log(`I had ${this.food} and ${this.drink} for lunch at ${location}`)
}
sayLunch.call(lunchObj, "Taco Bell") // I had tacos and water for lunch at Taco Bell
Hmm, tacos sound good 🤤. If the function accepts multiple arguments, we can pass them too:
function sayLunch(location, company, time){
console.log(`I had ${this.food} and ${this.drink} for lunch at ${location} with ${company} in the ${time}`)
}
sayLunch.call(lunchObj, "Taco Bell", "Jon and Juan", "afternoon") // I had tacos and water for lunch at Taco Bell with Jon and Juan in the afternoon
Using apply
apply
works like call
. The only difference is the way they accept function arguments. apply
uses array instead of separated by comma: myFunction.apply(obj, [arg1, arg2, argn])
Using our example earlier, but with apply
:
const lunchObj = {
food: 'tacos',
drink: 'water'
}
function sayLunch(location, company, time){
console.log(`I had ${this.food} and ${this.drink} for lunch at ${location} with ${company} in the ${time}`)
}
sayLunch.apply(lunchObj, ["Taco Bell", "Jon and Juan", "afternoon"])
We can take advantage of apply
's array arguments with ES6's spread operator
Here is a shameless copy-paste from mozilla page:
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// expected output: 6
console.log(sum.apply(null, numbers));
// expected output: 6
Keep in mind we can use call
and/or apply
into built-in functions, not custom functions. Something like this:
const someArr = ["foo", "bar", "baz"];
console.log.apply(null, someArr) // foo bar baz
And if we want to get fancy and append a new argument into someArr
:
console.log.apply(null, ['hello', ...someArr]) // hello foo bar baz
How to remember call vs apply arguments
A trick to remember which one is which is to look at their first letter (credit SO)
- A -> Apply -> Array
- C -> Comma -> Call
We only scratched the surface, but hopefully this should be enough to apply (pun intended 😎) your knowledge for more advanced stuff!
Top comments (6)
i read a lot of article about
call
andapply
, but still didnt get the idea WHY to use it. why should i introduce these methods to the project (which might be unknown for some), when i can write less, but a more straightforward code?your example for
call
is the followinginstead of this, why shouldnt i just write
am i missing something?
Hey kristoftombacz , thanks for replying!
That's a good question, thanks for bringing it up! I used that example because I think that is easiest to understand/ to make a point. I aimed this article for simplicity, I apologize for not being the most practical.
As for the real life application, here are two, I am sure there are myriads more:
What if you want to call private function but don't want to expose it to public? We can use
call
. Here is an example (source):What if you have an object that you later decide, "hey, this is useful, I want to extend this object to use with other attributes!".
Here is another example (souce)
And instead of rewriting the object and going through a lot of headache (say this Dave object has been around for years - who knows where else it is being used and who knows what will break if we modify it? 😅) If I want to rewrite one, that does not sound DRY. Instead I could do something like
Hope this makes sense. Let me know if I can help answer any other question! 😁
I'd also avoid
this
as much as possible...Love the simplicity and especially the trick about how to remember the difference.
But I am missing the part "When to use call and when to use apply", which I was most interested in ;-) Is it just about preference?
It just depends on the structure of your arguments.
call
is useful for manually calling a function where you have explicitly defined arguments.But sometimes you have an array of arguments and you want to programmatically call a function with them, that's where
apply
is useful.That said, with the advent of the spread/rest operator (
...
),apply
is redundant.Hey Jannik! I'm glad you liked it.
As for the usage, it is mostly up to your preference. In addition to what Jake covered (for arguments), you can use
call
andapply
to givethis
inside a function a different object.Normally I'd do
someObj.sayName()
. But if one day I go back to reusesayName
, but I want to pass it a different name, you can just use call/apply.someObj.sayName.call({name: 'Russell'})
.It's like inheriting and reusing other object's properties.