Function Borrowing: Reusing Logic Without Inheritance

When working with JavaScript, we often create objects that share similar properties or behaviors. Ideally, we'd structure our code so these behaviors are shared through prototypes or classes. But what if you already have a method in one object and want to reuse it in another—without inheritance or duplicating code? That’s where function borrowing comes into play. What Is Function Borrowing? Function borrowing allows one object to use a method from another object by explicitly setting the context (this) for the method. This means you can reuse code without needing inheritance or copying methods across objects. Function borrowing is made possible using: call() apply() bind() A Practical Example Let’s imagine a scenario where you have a method that summarizes a user’s profile, but it's defined only on one object. const user = { name: "Alice", role: "Engineer", getSummary() { return `${this.name} works as a ${this.role}.`; } }; const manager = { name: "Bob", role: "Manager" }; The user object has a getSummary method. The manager object has similar data, but no such method. Instead of copying the function, we can borrow it: console.log(user.getSummary.call(manager)); // Output: "Bob works as a Manager." We’ve borrowed getSummary from user and made it work on manager by setting this to manager using call(). Using apply() and bind() All three methods—call, apply, and bind—allow us to set the this value for a function. The difference lies in how they accept arguments and when they execute. apply() This works just like call(), but takes arguments as an array. function introduce(location, company) { return `${this.name} is a ${this.role} based in ${location}, working at ${company}.`; } const intern = { name: "Charlie", role: "Intern" }; console.log(introduce.apply(intern, ["New York", "TechCorp"])); // Output: "Charlie is an Intern based in New York, working at TechCorp." bind() bind() doesn’t immediately execute the function. Instead, it returns a new function that remembers the this value. const describeIntern = introduce.bind(intern, "New York", "TechCorp"); console.log(describeIntern()); // Output: "Charlie is an Intern based in New York, working at TechCorp." This is useful when you need a function reference that’s already bound to the right context—perhaps to be called later in an event handler or callback. Why Use Function Borrowing? Function borrowing can be handy in real-world scenarios, especially when: You’re dealing with third-party objects that don’t have methods you need. You want to avoid inheritance just to share one or two methods. You want to keep utility methods in one place, reducing duplication. A classic use case is working with array-like objects that don’t have array methods. For example: function getNumbers() { const argsArray = Array.prototype.slice.call(arguments); return argsArray.map(Number); } console.log(getNumbers("1", "2", "3")); // Output: [1, 2, 3] Here, arguments is not a real array. By borrowing slice() from Array.prototype, we turn it into an actual array and gain access to methods like map(). Should You Use It Often? Not necessarily. Function borrowing is best used: As a temporary workaround. In isolated cases where refactoring for inheritance is overkill. When extending native objects like arguments or NodeList. If you're designing a new structure from scratch, prefer class inheritance or utility functions. But for legacy code, DOM manipulation, or quick fixes, function borrowing can be very effective. Final Thoughts Function borrowing in JavaScript offers flexibility in how we structure and reuse code. While it’s not a replacement for inheritance or good design, it’s a powerful tool when used thoughtfully. Whether you're manipulating DOM collections or sharing methods between objects, understanding how to control this with call, apply, and bind can make your JavaScript cleaner and more adaptable. Want to keep things DRY and avoid duplicating methods? Borrow wisely. I’ve been actively working on a super-convenient tool called LiveAPI. LiveAPI helps you get all your backend APIs documented in a few minutes With LiveAPI, you can quickly generate interactive API documentation that allows users to execute APIs directly from the browser. If you’re tired of manually creating docs for your APIs, this tool might just make your life easier.

Apr 23, 2025 - 20:40
 0
Function Borrowing: Reusing Logic Without Inheritance

When working with JavaScript, we often create objects that share similar properties or behaviors.

Ideally, we'd structure our code so these behaviors are shared through prototypes or classes.

But what if you already have a method in one object and want to reuse it in another—without inheritance or duplicating code?

That’s where function borrowing comes into play.

What Is Function Borrowing?

Function borrowing allows one object to use a method from another object by explicitly setting the context (this) for the method.

This means you can reuse code without needing inheritance or copying methods across objects.

Function borrowing is made possible using:

  • call()
  • apply()
  • bind()

A Practical Example

Let’s imagine a scenario where you have a method that summarizes a user’s profile, but it's defined only on one object.

const user = {
  name: "Alice",
  role: "Engineer",
  getSummary() {
    return `${this.name} works as a ${this.role}.`;
  }
};

const manager = {
  name: "Bob",
  role: "Manager"
};

The user object has a getSummary method. The manager object has similar data, but no such method. Instead of copying the function, we can borrow it:

console.log(user.getSummary.call(manager));
// Output: "Bob works as a Manager."

We’ve borrowed getSummary from user and made it work on manager by setting this to manager using call().

Using apply() and bind()

All three methods—call, apply, and bind—allow us to set the this value for a function. The difference lies in how they accept arguments and when they execute.

apply()

This works just like call(), but takes arguments as an array.

function introduce(location, company) {
  return `${this.name} is a ${this.role} based in ${location}, working at ${company}.`;
}

const intern = { name: "Charlie", role: "Intern" };

console.log(introduce.apply(intern, ["New York", "TechCorp"]));
// Output: "Charlie is an Intern based in New York, working at TechCorp."

bind()

bind() doesn’t immediately execute the function. Instead, it returns a new function that remembers the this value.

const describeIntern = introduce.bind(intern, "New York", "TechCorp");
console.log(describeIntern());
// Output: "Charlie is an Intern based in New York, working at TechCorp."

This is useful when you need a function reference that’s already bound to the right context—perhaps to be called later in an event handler or callback.

Why Use Function Borrowing?

Function borrowing can be handy in real-world scenarios, especially when:

  • You’re dealing with third-party objects that don’t have methods you need.
  • You want to avoid inheritance just to share one or two methods.
  • You want to keep utility methods in one place, reducing duplication.

A classic use case is working with array-like objects that don’t have array methods. For example:

function getNumbers() {
  const argsArray = Array.prototype.slice.call(arguments);
  return argsArray.map(Number);
}

console.log(getNumbers("1", "2", "3"));
// Output: [1, 2, 3]

Here, arguments is not a real array. By borrowing slice() from Array.prototype, we turn it into an actual array and gain access to methods like map().

Should You Use It Often?

Not necessarily. Function borrowing is best used:

  • As a temporary workaround.
  • In isolated cases where refactoring for inheritance is overkill.
  • When extending native objects like arguments or NodeList.

If you're designing a new structure from scratch, prefer class inheritance or utility functions.

But for legacy code, DOM manipulation, or quick fixes, function borrowing can be very effective.

Final Thoughts

Function borrowing in JavaScript offers flexibility in how we structure and reuse code.

While it’s not a replacement for inheritance or good design, it’s a powerful tool when used thoughtfully.

Whether you're manipulating DOM collections or sharing methods between objects, understanding how to control this with call, apply, and bind can make your JavaScript cleaner and more adaptable.

Want to keep things DRY and avoid duplicating methods? Borrow wisely.

I’ve been actively working on a super-convenient tool called LiveAPI.

LiveAPI helps you get all your backend APIs documented in a few minutes

With LiveAPI, you can quickly generate interactive API documentation that allows users to execute APIs directly from the browser.

Image description

If you’re tired of manually creating docs for your APIs, this tool might just make your life easier.