#Functions#Polyfill

Function.prototype.bind Polyfill

Implement Function.prototype.bind from scratch, including partial application and the new-operator edge case that almost nobody gets right.

By Pratik RaiHard

Function.prototype.bind returns a new function with this permanently fixed and, optionally, some leading arguments pre-filled. It is by far the hardest of the three context methods to reimplement, because unlike call and apply it does not invoke anything — it manufactures a function that has to behave correctly in situations you do not control, including being used with new.

Why implement it yourself

call and apply are one-liners once you see the trick. bind is a genuine design problem. It has to handle partial application across two separate call sites, preserve constructor behaviour, and get length and name right on the function it returns. Almost every tutorial implementation gets the new case wrong, which makes it a reliable way for an interviewer to find out whether you understand what new actually does.

What the native method guarantees

JSfile.javascript
1function greet(greeting, name) { 2 return `${greeting}, ${name}! I am ${this.role}.`; 3} 4 5const bound = greet.bind({ role: 'admin' }, 'Hello'); 6bound('Ada'); // "Hello, Ada! I am admin."

Four properties matter:

  • this is fixed at bind time and cannot be overridden later — not by call, not by apply, not by a second bind.
  • Arguments passed at bind time are prepended to arguments passed at call time.
  • If the bound function is used with new, the bound this is ignored and the newly created object wins.
  • The returned function's length is the original's length minus the number of pre-bound arguments, floored at zero.

A naive version, and where it breaks

JSfile.javascript
1Function.prototype.myBind = function (thisArg, ...boundArgs) { 2 const fn = this; 3 return function (...callArgs) { 4 return fn.apply(thisArg, [...boundArgs, ...callArgs]); 5 }; 6};

This handles context and partial application correctly. It fails the constructor case:

JSfile.javascript
1function Point(x, y) { this.x = x; this.y = y; } 2const BoundPoint = Point.myBind(null); 3const p = new BoundPoint(1, 2); 4p.x; // undefined — `this` was forced to null instead of the new object

new BoundPoint(...) creates a fresh object and passes it as this, but the inner apply overwrites it with thisArg. The instance is left empty, and p instanceof Point is false.

Handling new

The fix is to detect construction and skip the bound this when it happens. The reliable signal is that during a new call, the inner function's this is an instance of the bound function:

JSfile.javascript
1Function.prototype.myBind = function (thisArg, ...boundArgs) { 2 if (typeof this !== 'function') { 3 throw new TypeError('Bind must be called on a function'); 4 } 5 6 const targetFn = this; 7 8 function bound(...callArgs) { 9 const isConstructorCall = this instanceof bound; 10 return targetFn.apply( 11 isConstructorCall ? this : thisArg, 12 [...boundArgs, ...callArgs] 13 ); 14 } 15 16 // Inherit the prototype chain so `instanceof` still works. 17 if (targetFn.prototype) { 18 bound.prototype = Object.create(targetFn.prototype); 19 } 20 21 Object.defineProperty(bound, 'length', { 22 value: Math.max(0, targetFn.length - boundArgs.length), 23 configurable: true, 24 }); 25 Object.defineProperty(bound, 'name', { 26 value: `bound ${targetFn.name}`, 27 configurable: true, 28 }); 29 30 return bound; 31};

bound is a function declaration rather than an arrow so that it gets its own this — an arrow would capture the enclosing scope and the instanceof check would be meaningless.

The Object.create(targetFn.prototype) line is what makes new BoundPoint(1, 2) instanceof Point true. Assigning bound.prototype = targetFn.prototype directly would also work for instanceof, but it links the two prototypes so that mutating one affects the other.

Edge cases worth knowing

Binding twice does nothing the second time. fn.bind(a).bind(b) is still bound to a. The second bind fixes this for the already-bound wrapper, and that wrapper ignores it. This surprises people who expect rebinding to work.

Arrow functions cannot be bound. They capture this lexically. bind returns a new function without error, but this inside it is unchanged. Same for call and apply.

Every bind allocates. Calling .bind(this) inside render creates a new function on every render, which breaks referential equality and defeats memoisation on child components. This is the practical reason React moved to class fields and hooks.

length is not just cosmetic. Currying utilities and some functional libraries inspect fn.length to decide whether they have enough arguments. Getting it wrong breaks them in ways that are hard to trace.

Common follow-ups

"What does new actually do?" The real question hiding inside this exercise. It creates an object whose prototype is the constructor's prototype, calls the constructor with that object as this, and returns it — unless the constructor returns an object of its own, which then wins.

"Implement call and apply too." Both are simpler, and the natural warm-up.

"How is this different from an arrow function in a class field?" A class field arrow captures this once per instance at construction; bind produces a new function per call unless you store it. Both solve the same problem with different allocation profiles.

Key takeaways

  • bind returns a function; it does not invoke one.
  • Detect construction with this instanceof bound and prefer the new object over the bound this.
  • Set bound.prototype = Object.create(target.prototype) so instanceof survives.
  • Bound arguments are prepended, and length shrinks accordingly.
  • Rebinding an already-bound function has no effect.

Goal: Implement myBind with partial application. Bonus: handle the `new` operator case.

Frequently asked questions

How is bind different from call and apply?
`call` and `apply` invoke the function immediately. `bind` invokes nothing — it returns a new function with `this` permanently fixed and any supplied arguments pre-filled. That difference is why it is the hardest of the three to implement.
What is partial application in this context?
Arguments passed to `bind` are prepended to whatever the returned function is later called with. `fn.bind(ctx, 1)(2, 3)` runs as `fn.call(ctx, 1, 2, 3)`. Concatenating the two argument lists in the right order is a common place to lose a mark.
What happens when a bound function is used with new?
The bound `this` is ignored. The specification says construction wins, so `new (fn.bind(ctx))()` creates a fresh object and uses that as `this`, not `ctx`. A complete implementation detects construction — historically with an `instanceof` check on the prototype chain, now more cleanly with `new.target` — and must also link the prototype so `instanceof` still works against the original function.
What are the follow-ups?
Whether binding twice re-binds (it does not — the first `this` sticks), and how `bind` interacts with arrow functions, which have no own `this` to bind in the first place.

Related Challenges

Continue learning with these related challenges

View All
JavaScript

Function.prototype.apply Polyfill

Implement Function.prototype.apply from scratch — identical to call except arguments arrive as a single array.

JavaScript · Functions · PolyfillsPratik Rai ·

JavaScript

Function.prototype.call Polyfill

Implement a Function.prototype.call polyfill from scratch. Master JavaScript this binding, execution context, primitive boxing, and safe property assignment techniques.

JavaScript · Functions · thisPratik Rai ·

JavaScript

Array.prototype.map Polyfill

Implement Array.prototype.map from scratch. Master callback signatures, thisArg binding, and sparse-array hole preservation.

JavaScript · Arrays · PolyfillsPratik Rai ·