So let's start with what method borrowing in javascript is? where we can use it? and how to do it?
As the name says method borrowing
, we can borrow i.e use methods of one object with another object.
Suppose we want to use some methods which are present in object A with object B then how we can achieve this.
Let's see an example:
const person1 = {
fullName: "Adarsh Balak",
printName: function() {
console.log(this.fullName)
}
}
const person2 = {
fullName: 'John Doe'
}
person1.printName() // Adarsh Balak
Now here person1 can call printName
method as its present in that object, but what about person2, if person2 wants to print fullName
then it will need printName
, so for that javascript provides call()
, apply()
and bind()
methods. Using this we can solve the above problem.
1. call()
Let's see an example:
const person1 = {
fullName: "Adarsh Balak",
printName: function() {
console.log(this.fullName)
}
}
const person2 = {
fullName: 'John Doe'
}
person1.printName() // Adarsh Balak
person1.printName.call(person2) // John Doe
So what we did is, when printName
is called using the call()
method and which sets the value of this
to person2
so now wherever this
is used inside printName
method instead of person1 call()
sets the this
context to the person2
. Using the call()
method we don't need to create printName
in person2 we can just borrow it from a person1.
The call()
method's first argument is the this
ie the object to which we want the method which is called using call()
should refer to and others are comma-separated arguments ie call(thisArg, arg1, arg2, ...., argN)
Let's see another example:
const person1 = {
fullName: "Adarsh Balak",
printName: function(age, city) {
console.log(this.fullName, age, city)
}
}
const person2 = {
fullName: 'John Doe'
}
person1.printName.call(person2, 22, 'Mumbai') // John Doe 22 Mumbai
2. apply()
Now the only difference the apply()
has is that it takes all the other arguments except the first, in an array-like object ie apply(thisArg, [arg1, arg2, ...argN])
. So our method will look like person1.printName.apply(person2, [22, 'Mumbai'])
.
3. bind()
Now let's understand bind()
, so it works similar to call()
but instead of calling the method it returns a new function whose this
context is bound together with the method onto which the bind()
was called. Let's see with a different example:
function printName(age, city) {
console.log(this.fullName, age, city)
}
const person2 = {
fullName: 'John Doe'
}
const bindedPrintName = printName.bind(person2, 22, 'Mumbai')
bindedPrintName() // John Doe 22 Mumbai
Now printName
is present at a global level rather than inside of an object.
Gotchas with arrow functions
- For arrow functions the
call()
,apply()
andbind()
does not work as expected, because arrow functions do not have their ownthis
, so they inheritthis
value from the parent context where the arrow function was defined. - So when
call()
,apply()
andbind()
used with arrow function the first argument iethis
context is ignored.
const printName = (age, city) => {
console.log(this.fullName, age, city)
}
const person2 = {
fullName: 'John Doe'
}
printName.call(person2, 22, 'Mumbai') // undefined 22 'Mumbai'
Conclusion
call()
,apply()
andbind()
is used to call methods in some other scope, ie when we give thethis
context with the help of the call, apply and bind what happens is the method behaves as if it was present in that context or object.call()
takes the first argument as thisArgument and the rest as comma-separated values.apply()
also takes the first argument as thisArgument but rests in an array.bind()
works similar tocall()
instead of calling it returns a new function.- Arrow functions does not work as expected with
call()
,apply()
andbind()
.
References