So functions have methods, we're in Inception, but don’t worry, you’ll make it, with flying colors too!
The first method is the aptly-named call(). It lets us call a function with a given set of arguments, so just like a regular call using the parentheses operator, with a critical twist though: we start by specifying the this we want to use!
When you think about it, it’s rather expected that we get such a feature: considering that JS doesn’t ever define a specific this itself except in the “Subject, Verb and Complement” scenario, it makes sense to provide a mechanism for specifying this whenever we need it.
So for instance, keeping it simple, when JS sees elodie.sayHi('Anna'), it implements our golden rule by actually running elodie.sayHi.call(elodie, 'Anna'). The semantics are identical.
Just think about how powerful that is: it means we can grab any function, however we go about it, and call it with any this! This opens up a very wide array of opportunities, and indeed many facets of popular libraries and APIs would be quite impossible to provide without that core language feature. Without call(), say goodbye to React or jQuery, my friends! We’d still be writing blinking rotating texts in Comic Sans on Geocities, I’m tellin’ya.
(Not getting that Geocities reference? How lucky you are, when I'm already old.)
Still, call() has a dark side: when invoked on an arrow function, it silently fails. It doesn’t blow up or anything: but because an arrow function cannot, by definition, hold its own this, as the professional saying goes: tough luck.
Let's see that in practice.
This code is designed to run on Node.js, so the current “global this” for the module is in fact the exports object for the CommonJS module that file represents. It is the very same object as the exports identifier the CommonJS interface provides. Hey, perhaps you just learned something there.
We have this small, traditionally-declared sayHi() function: it can have its own this and arguments. So if we write sayHi.call(autore, 'Elliott') all should be dandy.
On the other hand, the greet() arrow function, despite its identical signature and body, doesn’t get custom entries for these in its environment record, so we’re likely going to go off-rails there…
So let’s see (demo). Aaaaah, there we go, sayHi() does have its this set to aurore, and arguments does bind to whom, hence 'Elliott'. Good so far. But for greet(), what the—? The this is obviously something else, as this.name is undefined (and indeed, the exports object has no name property). As for arguments, it actually refers to the first argument the wrapper CommonJS function for the module got, which is the exports object, hence the zomg property and its value 'OH NOES'.
Don’t you just love call() on arrow functions? No warning, no disclaimer, no nothing: there’s your outlandish bug. Told ya: arrow functions are not a silver bullet.
Still, call() is quite handy. The only thing is, you must know exactly how many arguments you need to pass, because they’re passed individually in the call. True, starting with ES2015 we could spread the arguments array, making it more flexible, but before that, which means all IE versions, we just couldn’t, so how can we be a bit more flexible in terms of arity?