Back to JavaScript
JavaScript
easy
mid

How would you write a custom implementation of Function.prototype.bind?

`bind` returns a new function with `this` permanently bound and optionally some pre-applied arguments. Implementation: `Function.prototype.myBind = function(thisArg, ...preset) { const fn = this; return function (...rest) { return fn.apply(thisArg, [...preset, ...rest]); }; }`. Subtlety: bound function called with `new` should ignore thisArg and construct.

3 min read·~12 min to think through

Minimal bind

js
Function.prototype.myBind = function (thisArg, ...preset) {
  const fn = this;
  return function (...rest) {
    return fn.apply(thisArg, [...preset, ...rest]);
  };
};

Tests:

js
function greet(greeting, name) { return greeting + ", " + name + " (this=" + this.tag + ")"; }
const ctx = { tag: "A" };

greet.myBind(ctx, "Hi")("Sam");
// "Hi, Sam (this=A)"

Handling new

The spec says: a bound function called with new constructs the original target, ignoring the bound this:

js
Function.prototype.myBind = function (thisArg, ...preset) {
  const fn = this;
  function bound(...rest) {
    const isNew = this instanceof bound;
    return fn.apply(isNew ? this : thisArg, [...preset, ...rest]);
  }
  bound.prototype = Object.create(fn.prototype);   // so instanceof works
  return bound;
};

new bound(...) will have this instanceof bound === true, so we pass this (the freshly constructed object) instead of thisArg.

Why bound.prototype = Object.create(fn.prototype)

new bound() creates an object whose prototype is bound.prototype. Setting it to point at fn.prototype makes instance instanceof fn true — same behavior as native bind.

Edge cases worth knowing

  • Calling myBind on a non-function should throw TypeError. (Spec.)
  • Native bind disallows further bind calls overwriting this (first binding wins). Our impl above also does this — the inner fn won't see a re-bound this.
  • The returned function's .length should be Math.max(0, fn.length - preset.length) (spec). Skip in interview unless asked.

Arrow function

Arrows ignore bind on this (they capture lexically). Native and our polyfill both bind the args but thisArg is no-op for arrows.

Why people ask this

  • Tests prototype chain understanding.
  • Tests this, apply, closures together.
  • Bonus: shows you know what new does.

Interview framing

"bind returns a new function with this pre-set and optionally some args. The bare impl is a closure that captures this and the preset args, then calls fn.apply(thisArg, [...preset, ...rest]) when invoked. The subtle bit is new — a bound function called with new should construct the original target, ignoring the bound this. Detect with this instanceof boundFn and forward accordingly. Set bound.prototype = Object.create(fn.prototype) so instanceof checks still work. Spec niceties (length, no-rebind) are usually skipped unless asked."

Follow-up questions

  • What does `new` do on a bound function?
  • Why does instanceof work on the bound function?
  • Why don't arrow functions bind this?

Common mistakes

  • Forgetting the new case.
  • Losing this binding when using arrow inside bind (would always lexical).
  • Not chaining preset and call-time args.

Performance considerations

  • Native bind is slightly faster due to engine optimization, but the difference is negligible outside hot loops.

Edge cases

  • Binding non-function (should TypeError).
  • Re-binding (spec freezes first this).
  • Arrow functions ignore thisArg.

Real-world examples

  • Polyfilling for legacy engines, React class methods pre-arrow patterns, event-handler binding utilities.

Senior engineer discussion

Seniors handle the `new` case and the prototype chain step. They mention the spec rules (length, re-bind) even if they don't fully implement them.

Related questions