Javascript: call(), apply() and bind()
“this” refresher
In Object Oriented JS we learned that in JS, everything is an object. Because everything is an object, we came to understand that we could set and access additional properties to functions.
Setting properties to a function and additional methods via the prototype is super awesome … but how do we access them?!??!
We were introduced to the this keyword. We learned that every function gets this property automatically. So at this point in time, if we were to create a mental model of our function execution context( I am not the only one who does this!… right?!?!), it would look something like this:
It took us a little while to get comfortable with the this keyword, but once we did we began to realize how useful it is. this is used inside a function, and will always refer to a single object — the object that invokes (calls) the function where “this” is used.
But life isn’t perfect. Sometimes, we lose our this reference. When that happens, we end up using confusing hacks to save our reference to this. Check out this confusing hack from our localStorage exercise:
So why did I need to save a this reference? Because inside deleteBtn.addEventListener, this refers to the deleteBtn object. This is unfortunate. Is there a better solution?
call(), apply() and bind() — a new hope
Up until now we have treated functions as objects that are composed of a name (optional, can also be an anonymous function) and the code it executes when it is invoked. But that isn’t the entire truth. As a truth loving person, I must let you know that a function actually looks closer to the following image:
What is this??????? Don’t worry! I will now walk through these 3 similar methods that appear on every function with examples. Rejoice!
bind()
The official docs say: The bind() method creates a new function that, when called, has its this keyword set to the provided value. (It actually talks about even more stuff, but we’ll leave that for another time :) )
This is extremely powerful. It let’s us explicitly define the value of this when calling a function. Let’s look at cooooode:
var player = {
firstname: 'Mohamed',
lastname: 'Salah ',
getPlayerName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
};
var playerName = function() {
console.log(this.getPlayerName() + 'I choose you!');
};
var logPlayer = playerName.bind(player); // creates new object and binds player. 'this' of player === player now
logPlayer(); // 'Mohamed Salah I choose you!'
Let’s break it down. When we use the bind() method:
- the JS engine is creating a new playerName instance and binding player as its this variable. It is important to understand that it copies the playerName function.
- After creating a copy of the playerName function it is able to call logPlayer(), although it wasn’t on the player object initially. It will now recognizes its properties (Mohamed and Salah) and its methods.
And the cool thing is, after we bind() a value we can use the function just like it was any other normal function. We could even update the function to accept parameters, and pass them like so:
var player = {
firstname: 'Mohamed',
lastname: 'Salah ',
getPlayerName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
};
var playerName = function(clubName, date) {
console.log(this.getPlayerName() + 'I choose you!');
console.log(date + this.getPlayerName() + 'agreed a transfer to' + clubName
);
};
var logPlayer = playerName.bind(player); // creates new object and binds player. 'this' of player === player now
playerName('Liverpool', 'On 22 June 2017'); // On 22 June 2017 Mohamed Salah agreed a transfer to Liverpool.
call(), apply()
The official docs for call() say: The call() method calls a function with a given this value and arguments provided individually.
What that means, is that we can call any function, and explicitly specify what this should reference within the calling function. Really similar to the bind() method! This can definitely save us from writing hacky code (even though we are all still hackerzzz).
The main differences between bind() and call() is that the call()method:
- Accepts additional parameters as well
- Executes the function it was called upon right away.
- The call() method does not make a copy of the function it is being called on.
call() and apply() serve the exact same purpose. The only difference between how they work is that call() expects all parameters to be passed in individually, whereas apply() expects an array of all of our parameters. Example:
var player = {
firstname: 'Mohamed',
lastname: 'Salah ',
getPlayerName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
};
var playerName = function(clubName, date) {
console.log(date + this.getPlayerName() + 'agreed a transfer to' + clubName
);
};
playerName.call(player,'Liverpool', 'On 22 June 2017'); // On 22 June 2017 Mohamed Salah agreed a transfer to Liverpool.
playerName.apply(player,['Liverpool', 'On 22 June 2017']); // On 22 June 2017 Mohamed Salah agreed a transfer to Liverpool.
These built in methods, that exist on every JS function can be very useful. Even if you do not end up using them in your day to day programming, you will still run into it often when reading other peoples code.
Software Developer | Senior Front-End (JavaScript ES6, React, Next, Redux, Angular, Node) | Jr CyberSecurity (Owasp, Ethical Hacking)
6 年Versus no! serían más bien sus diferencias cada una aplica a una situación diferente las 3 son necesarias según el caso ninguna es mejor que la otra
Solutions Architect at Sopra HR Software | TOGAF? 9 | Scrum Master?| AWS Solutions Architect ?| LPI DevOps? | RHCSA ?
6 年Wonderful contribution