Executing methods in JavaScript; Call Vs Apply

ST

Seb Toombs

Mar 14 2021 ()

2 min read

If you're just here for the cheat sheet;

Sometimes in JavaScript, you don't want to just execute a function the 'normal' way.

E.g. I might have a function like this;

function sayHi(name) {
  console.log(`Hi ${name}`);
}

And the normal way to call it would be: sayHi('Seb');

And that's all fine and good.

But let's say I want to call a function/method belonging to one object for a different object. Or make sure the 'this' argument is bound to the correct scope (if you ever wrote React class components, you might have seen this when binding event listeners)

Well in these cases (and many more) call and apply methods are really handy.

I'm going to use the example here of using call or apply to invoke a method and explicitly specify the this argument. There are many other use cases for both these methods.

It's also worth noting that the two methods can pretty much be used interchangeably, with the main difference being the way arguments are passed.

I just want to know the difference!

Just want to know the difference between the two? I got you;

Here's a really useful mnemonic;

(C)all accepts a (C)omma separated list
(A)pply accepts an (A)rray

// Call accepts a (C)omma separated list
console.log.call(null, "foo", "bar", "baz");
// logs => foo bar baz

// Apply accepts an (A)rray of arguments
console.log.call(null, ["foo", "bar", "baz"]);
// logs => foo bar baz

Done! Using console.log as the example, call takes a comma separated list of arguments, and apply takes an array.

Here's a slightly more detailed example

const logger = (...args) => { // Accept an unlimited list of arguments
  console.log(...args); // Log all the arguments
}

// Call accepts a (C)omma separated list
logger.call(null, "foo", "bar", "baz");
// logs => foo bar baz

// Apply accepts an (A)rray of arguments
logger.call(null, ["foo", "bar", "baz"]);
// logs => foo bar baz

Show me what it's good for!

So the above examples were pretty contrived for the purposes of showing the difference.

Let's say you want to invoke a method and explicitly set the this argument.

function greet(name) {
  console.log(`${this.greeting} ${name}`);
}

greet();
// logs => undefined undefined

const obj = {
  greeting: 'Hi'
};

greet.call(obj, 'Seb')
// logs => Hi Seb

// OR

greet.apply(obj, ['Seb'])
// logs => Hi Seb