Skip to content

Instantly share code, notes, and snippets.

@bignimbus
Last active August 29, 2015 14:01
Show Gist options
  • Save bignimbus/45e9411fdf31478d0fac to your computer and use it in GitHub Desktop.
Save bignimbus/45e9411fdf31478d0fac to your computer and use it in GitHub Desktop.
A brief explanation of JavaScript's native .apply() and .call() functions.
// In a recent interview I was stumped by a question about JS's native
// function.apply() and function.call() methods. I resolved to learn more
// about why these methods are useful to a JS developer. Here's what I now
// understand:
// let's make a simple function that introduces an individual.
// We pass arguments defining the interests of the individual.
// The greeting is personalized by the value of this.name.
function introduceMe (interest1, interest2) {
var that = this;
if (!this.name) this.name = '... I forgot.';
return {
greeting: 'Hi, my name is ' + this.name,
interests: [interest1, interest2],
context: that //for reference
}
}
// Now, for laughs, I'll call this function in the global context.
introduceMe('JavaScript', 'music');
// => Object {greeting: "Hi, my name is ... I forgot.", interests: Array[2], context: Window}
// This function is clearly socially awkward. Let's see if I
// can help the poor thing out.
// Here are paul and john - they're objects (of our admiration).
var paul = {},
john = {};
// How are you going to introduce yourself without a name?
paul.name = 'Paul';
john.name = 'John';
// Paul needs a standard way to introduce himself.
// That way, he won't freeze up. Good thing we have introduceMe()!
paul.introduction = introduceMe('bass', 'Walrus');
// => Object {greeting: "Hi, my name is ... I forgot.", interests: Array[2], context: Window}
// Poor Paul. John - you're up!
john.introduction = introduceMe('guitar', 'Yoko');
// => Object {greeting: "Hi, my name is ... I forgot.", interests: Array[2], context: Window}
// Looks like our trouble is that pesky THIS.
// Maybe they need a friend to come and introduce them.
// In some cases, a simple constructor statement could work.
paul.introduction = new introduceMe('bass', 'Walrus');
// => Object {greeting: "Hi, my name is ... I forgot.", interests: Array[2], context: introduceMe}
//
// But not this case! paul.introduction does not have access to
// paul.name, therefore his introduction is destined to fail.
// furthermore, the value of THIS is still not paul himself.
// I am heading in the right direction, though.
// As he always does, John is going to try something a little different.
john.introduction = introduceMe.call(john, 'guitar', 'Yoko');
// => Object {greeting: "Hi, my name is John", interests: Array[2], context: Object}
//
// SUCCESS! john can now introduce himself without fear of social anxiety.
// And who says programmers don't have people skills?
// When we invoke a function using the .call() method, we add one argument.
// The first argument in .call() overrides the default value of THIS.
// So even though we are calling introduceMe() from john.introduction,
// we can still set the john Object as THIS.
// Paul, being the organized fellow he is, is going to refine this strategy
// a bit with the .apply() method.
// First, let's define paul's interest in a separate array object:
paul.faves = ['bass', 'Walrus'];
paul.introduction = introduceMe.apply(paul, paul.faves);
// => Object {greeting: "Hi, my name is Paul", interests: Array[2], context: Object}
// Not only did paul's approach work just as well as john's (at a very
// slight performance cost), but he opened up the possibility of
// introducing an arbitrary number of arrays with a few obvious tweaks.
// That's the main difference between .call() and .apply(). Here's a chart:
/*
Need to call a function and override THIS.
|
|---> Use function.call() or function.apply()
|
|---> Which one?
|
|---> .call() has a slight performance advantage but needs to pass comma-separated parameters.
|
|---> .apply() can pass all parameters as an array object.
*/
@Pushplaybang
Copy link

thanks for this - context can be really confusing and really is one of those things you need to play with to really "get", I still find it catches me from time to time.

@bignimbus
Copy link
Author

Glad I could help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment