JavaScript .call() .apply() .bind() simplified.
azmy60
Posted on March 28, 2022
These three methods are part of the Function.prototypes
. Basically, what they do is change the reference of this
so it points to the "object target".
const sayHi = function() {
console.log(`Hi ${this.name}!`);
};
const person = {
name: "foxy",
};
sayHi.call(person); // Hi foxy!
sayHi.apply(person); // Hi foxy!
sayHi.bind(person)(); // Hi foxy!
In this example, the 3 methods are referencing the person
object so this.name
is now person.name
. And notice that the object reference is passed as the first argument.
.call()
Takes 1 or more arguments. The 2nd argument onward will be passed to the function.
const addItems = function(item1, item2){
this.items.push(item1, item2);
};
const cart = {
items: [],
};
// Add items to cart
addItems.call(cart, 'lettuce', 'watermelon');
p.s. we can use arguments
instead of item1, item2
:
const addItems = function(){
this.items.push(...arguments);
};
.apply()
Takes 1 or 2 arguments. The 2nd argument must be an array.
addItems.apply(cart, ['egg fried rice', 'cucumber']);
.bind()
Takes only 1 argument. In contrast with the above methods, this method will not call the function at once. It returns a new function instead, so you have to call it later manually.
// Make a new function
const boundAddItems = addItems.bind(cart);
// Call it here
boundAddItems('milk', 'jellybeans', 'more jellybeans');
// Or pass it to another function
document.querySelector('button')
.addEventListener('click', boundAddItems)
Bonus example
Let's say we want to add an event listener to the entire <button>
in a document. We can use .querySelectorAll()
to retrieve the buttons, which will return a NodeList. A NodeList doesn't contain functions like .map()
or .forEach()
. But we can borrow these functions from Array.prototype and use it like this:
const buttons = document.querySelectorAll('button');
Array.prototype.forEach
.call(buttons, (el) => el.addEventListener('keydown', ...))
In javascript, Array is just an object. And so NodeList! Therefore, using the prototype methods of Array with an object is fine, as long as it is an array-like object.
A NodeList contains a collection of incrementing numbers, and a length
property, which is why it is similar to an Array.
Thanks for reading!
Links:
Function.prototypes.call() | MDN
Function.prototypes.apply() | MDN
Posted on March 28, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024