← all writing

Explicit Binding Using Call and Apply in JavaScript

In JavaScript, explicit binding is a powerful technique that allows you to explicitly specify the context (the this value) in which a function should be executed. Two essential methods for explicit binding are call and apply. Both methods let you say "execute this function in that object's context."

The call method

The call method allows you to invoke a function while explicitly setting the this value to a specified object. In other words, the call method invokes a function with a given this value and arguments provided individually. Here's the syntax:

functionName.call(thisArg, arg1, arg2, ...);

Example

const person = {
  name: 'Deepak',
  getName: function () {
    console.log(this.name);
  }
};
 
person.getName();                         // Deepak
 
const anotherPerson = {
  name: 'Piyush'
};
 
person.getName.call(anotherPerson);       // Piyush

In this example, we explicitly bind the getName function to the anotherPerson object using call. As a result, this inside getName refers to anotherPerson, allowing us to access its name property.

The apply method

The apply method is similar to call but takes an array of arguments as its second parameter. The apply method invokes a function with a given this value and arguments provided as an array. Here's the syntax:

functionName.apply(thisArg, [arg1, arg2, ...]);

Example

const person = {
  name: 'Deepak',
  getName: function () {
    console.log(this.name);
  }
};
 
person.getName();                          // Deepak
 
const anotherPerson = {
  name: 'Piyush'
};
 
person.getName.apply(anotherPerson);       // Piyush

In this example, we explicitly bind the getName function to the anotherPerson object using apply. As a result, this inside getName refers to anotherPerson, allowing us to access its name property.

Borrowing array methods

arguments objects (array-like objects) do not have array's methods, but we can invoke Array's methods explicitly by using call and apply.

function myFunction() {
  Array.prototype.push.call(arguments, "four");
  // Array.prototype.push.apply(arguments, ["four"]);
 
  console.log(arguments[3]);          // "four"
}
 
myFunction("one", "two", "three");

When to use call vs apply

When you don't know the number of arguments in advance, use apply (pass them as an array). Otherwise, use call.

Questions

Q6 assumes a non-strict / classic script context — the same window.name / strict-mode caveat from the previous chapter applies.

1. What is the output of the following program?

function getFullName(firstName, lastName) {
  console.log(`My name is ${firstName} ${lastName}`);
}
 
const anotherPerson = {
  firstName: 'Piyush',
  lastName: 'Nema'
};
 
getFullName.call(anotherPerson, 'Deepak', 'Sisodiya');

Answer — My name is Deepak Sisodiya

Explanation: Here, firstName and lastName inside the getFullName function refer to the arguments provided through the call method.

2. What is the output of the following program?

function getFullName(firstName, lastName) {
  console.log(`My name is ${this.firstName} ${this.lastName}`);
}
 
const anotherPerson = {
  firstName: 'Piyush',
  lastName: 'Nema'
};
 
getFullName.call(anotherPerson, 'Deepak', 'Sisodiya');

Answer — My name is Piyush Nema

Explanation: Here, this.firstName and this.lastName inside the getFullName function refer to the properties of the anotherPerson object provided through the call method. The arguments 'Deepak' and 'Sisodiya' are ignored because the function doesn't use its named parameters.

3. What is the output of the following program?

function greet(message) {
  console.log(`${message}, ${this.name}!`);
}
 
const person = {
  name: "Deepak",
};
 
greet.call(person, "Hello"); // What will this log?

Answer — Hello, Deepak!

Explanation: The call method explicitly sets the context (this) to the person object, so this.name is "Deepak", and the template literal produces "Hello, Deepak!".

4. What is the output of the following program?

function sum(a, b) {
  return a + b;
}
 
const numbers = [3, 7];
 
const result = sum.apply(null, numbers); // What will this log?
console.log(result);

Answer — 10

Explanation: The apply method invokes the sum function with the numbers array spread as arguments, effectively summing its elements.

5. What is the output of the following program?

function getName() {
  return this.name;
}
 
const person = { name: 'Deepak' };
 
console.log(getName.call(person));

Answer — Deepak

Explanation: The call method invokes the getName function with the person object as its context, allowing it to access the name property of the person object.

6. What is the output of the following program?

const getName = () => {
  return this.name;
};
 
const obj = { name: 'Deepak' };
 
console.log(getName.call(obj));

Answer — undefined

Explanation: Arrow functions don't have their own this binding; instead, they inherit it from the surrounding context, which in this case is the global context. Since the global context (window in a browser) doesn't have a name property, it returns undefined. Note that call's thisArg is ignored by arrow functions — that's the key takeaway here.