MediumMetaUberAmazonPegasystems

bind( ) polyfill

Prompt

Implement a polyfill for the JavaScript .bind() method. Add a myBind method to Function.prototype that works exactly like the native .bind(), without using .bind() itself.

Playground

Hint 1

When someone calls greet.myBind(person), the this inside myBind refers to greet (the function being bound). You'll need to save that reference because this will mean something different inside the returned function.

Hint 2

.bind() can pre-fill some arguments at bind time, and the rest get passed at call time. You need to combine both sets of arguments in the right order: bind-time arguments first, then call-time arguments.

Hint 3

You can't use .bind() itself, but you can use .apply() inside your implementation. .apply() lets you call a function with a specific this and an array of arguments.

Solution

Explanation

.bind() is different from .call() and .apply(). Those two execute the function immediately. .bind() doesn't execute anything. It takes a function and returns a brand new function with two things permanently locked in:

  1. What this should be
  2. Optionally, some arguments pre-filled

This is useful when you need to pass a function somewhere (like an event handler or a callback) but you want to make sure it always runs with the right this and the right arguments.

const greetAlice = greet.bind(person);
// greetAlice is a new function
// whenever you call greetAlice(), this = person

button.addEventListener('click', greetAlice);
// even when the browser calls greetAlice later,
// this will still be person, not the button

Why do we save this in a variable?

This is the part that trips people up. When someone writes greet.myBind(person), the this inside myBind is greet (the function we want to bind). We need to save it:

const fn = this; // fn = greet

Why? Because we're about to return a new function. When that new function gets called later (maybe seconds, maybe minutes later), this inside it won't be greet anymore. It'll be whatever object called it. By saving greet in fn now, we can use it later inside the returned function. This is a closure in action.

How partial application works

This is the other concept worth understanding. .bind() lets you "pre-fill" some arguments:

function add(a, b) {
return a + b;
}

const addFive = add.bind(null, 5);
addFive(3); // 8
addFive(10); // 15

addFive always passes 5 as the first argument. Whatever you pass when you call addFive becomes the second argument.

In our polyfill, we handle this with two sets of arguments:

  • bindArgs = arguments passed when .myBind() is called (e.g., [5])
  • callArgs = arguments passed when the returned function is called (e.g., [3])

We combine them: [...bindArgs, ...callArgs] gives us [5, 3]. Bind-time arguments always come first.

Walking through a full example

const person = { name: 'Alice' };

function introduce(greeting, punctuation) {
return `${greeting}, I am ${this.name}${punctuation}`;
}

const introduceAlice = introduce.myBind(person, 'Hi');
introduceAlice('!');
  1. myBind is called on introduce. fn = introduce, context = person, bindArgs = ['Hi']
  2. A new function is returned and stored in introduceAlice
  3. When we call introduceAlice('!'), callArgs = ['!']
  4. Combined args: ['Hi', '!']
  5. Internally it runs introduce.apply(person, ['Hi', '!'])
  6. introduce executes with this = person, greeting = 'Hi', punctuation = '!'
  7. Returns: "Hi, I am Alice!"

We wrap the polyfill in if (!Function.prototype.myBind) to avoid overwriting it if it already exists. This is standard practice for polyfills. You never blindly overwrite existing functionality.