Call, Apply, Bind & their Polyfills
What is call(), apply() & bind() ?
call(), apply() & bind() are inbuilt JavaScript methods available to all JavaScript functions. These methods are used to define the context of this
keyword or to change the context of this
keyword.
Suppose this
keyword is pointing to an object but we want it to point to some other object, let us understand this with an example:-
const person1 = {
name: 'Bobby'
}
const person2 = {
name: 'Deadpool',
getName(){
console.log(this.name) // this keyword is pointing to person2
}
}
person2.getName() // Deadpool
In the above example, getName() is printing Deadpool, because this keyword is pointing to the person2 object and the value of the name variable inside the person1 object is 'Deadpool'.
But how can we print 'Bobby', so to print 'Bobby', we have to change the context of this keyword from person2 to person1:-
const person1 = {
name: 'Bobby'
}
const person2 = {
name: 'Deadpool',
getName(){
console.log(this.name) // this keyword is pointing to person2
}
}
// this keyword context changed to person1
person2.getName.call(person1) // Bobby
call()
call(thisValue, args1, args2, ...)
method executes the function as soon as it is called. It accepts the this
value and arguments individually.
const person1 = {
name: 'Bobby'
}
const person2 = {
name: 'Deadpool',
getName(city,country){
// this keyword is pointing to person2
console.log(`My name is ${this.name} and I am from ${city}, ${country}`)
}
}
// this keyword context changed to person1
person2.getName.call(person1, 'Bhopal', 'India')
// My name is Bobby and I am from Bhopal, India
Apply()
The apply(thisValue, [args1, args2])
function is similar to the call
function. The only difference between call
and apply
is the difference in how arguments are passed.
In apply
, arguments are passed as an array.
const person1 = {
name: 'Bobby'
}
const person2 = {
name: 'Deadpool',
getName(city,country){
// this keyword is pointing to person2
console.log(`My name is ${this.name} and I am from ${city}, ${country}`)
}
}
// this keyword context changed to person1
person2.getName.apply(person1, ['Bhopal', 'India'])
// My name is Bobby and I am from Bhopal, India
Bind()
The bind(thisValue, args1, args2, ...)
function creates a copy of a function with a new value of the this
object.
It does not execute as soon as the function is called instead it makes a copy of that function and returns us the function so that we can use it later.
const person1 = {
name: 'Bobby'
}
const person2 = {
name: 'Deadpool',
getName(city,country){
// this keyword is pointing to person2
return(`My name is ${this.name} and I am from ${city},${country}`)
}
}
// this keyword context changed to person1
let fullName = person2.getName.bind(person1, 'Bhopal')
console.log(fullName('India'))
// My name is Bobby and I am from Bhopal, India
Polyfill for call()
Function.prototype.myCall = function(context={}, ...rest){
if(typeof(this) !== "function"){
throw new Error(this + 'is not a function')
}
context.fn = this
context.fn(...rest)
}
Example:-
const person1 = {
name: 'Bobby'
}
const person2 = {
name: 'Deadpool',
getName(city,country){
// this keyword is pointing to person2
console.log(`My name is ${this.name} and I am from ${city}, ${country}`)
}
}
// this keyword context changed to person1
person2.getName.myCall(person1, 'Bhopal', 'India')
// My name is Bobby and I am from Bhopal, India
Polyfill for apply()
Function.prototype.myApply = function(context={},arr){
if(typeof(this) !== 'function'){
throw new Error(this + 'is not a function')
}
context.fn = this
context.fn(...arr)
}
Example:-
const person1 = {
name: 'Bobby'
}
const person2 = {
name: 'Deadpool',
getName(city,country){
// this keyword is pointing to person2
console.log(`My name is ${this.name} and I am from ${city}, ${country}`)
}
}
// this keyword context changed to person1
person2.getName.myApply(person1, ['Bhopal', 'India'])
// My name is Bobby and I am from Bhopal, India
Pollyfill for bind()
Function.prototype.myBind = function(context={}, ...args){
if(typeof(this) !== 'function'){
throw new Error(this + 'is not a function')
}
context.fn = this
return function(...newArgs){
context.fn(...args, ...newArgs)
}
}
Example:-
const person1 = {
name: 'Bobby'
}
const person2 = {
name: 'Deadpool',
getName(city,country){
// this keyword is pointing to person2
return(`My name is ${this.name} and I am from ${city},${country}`)
}
}
// this keyword context changed to person1
let fullName = person2.getName.bind(person1, 'Bhopal')
console.log(fullName('India'))
// My name is Bobby and I am from Bhopal, India
Final Words
And that’s it for this blog.
I hope you’ve found this blog a good referencing resource and thank you for reading.
If this blog was helpful, please do like, comment and share. Thanks, see you in the next blog.✌️
Subscribe to my newsletter
Read articles from Bobby Sadhwani directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Bobby Sadhwani
Bobby Sadhwani
I'm a front-end developer focused on crafting clean and user friendly experiences.