AniUI Academy

Implement Function.prototype.bind, including new

hardFunctions & Closures+350 XPPractice

Writing a bind that fixes this and prepends arguments takes three lines. The reason this is an interview favourite is the other half of the spec: a bound function used as a constructor must ignore the bound receiver entirely, because new supplies its own this, and instances must still be instanceof the original function.

Implement myBind(fn, thisArg, ...boundArgs), where fn is an ordinary function declared with the function keyword. It returns a new function that, when called normally, invokes fn with this set to thisArg and with boundArgs followed by the call-time arguments, returning fn's result. The bound receiver wins permanently: calling the bound function as a method of some other object does not change this inside fn. When the bound function is called with new, thisArg is ignored and this inside fn is the newly constructed object; boundArgs are still prepended, the result is the new object (assuming fn returns nothing), the object inherits from fn.prototype so methods defined there are available, and instance instanceof fn is true. Your implementation must not use Function.prototype.bind, call or apply: one of the tests replaces all three with functions that throw.

Arguments

fnFunction
The function to bind. Must be a regular function so new works.
thisArgany
The receiver for normal calls. Ignored under new.
...boundArgsany[]
Arguments to prepend on every invocation of the bound function.

Returns

Function — A bound function callable normally or with new, with the correct receiver and prototype chain.

Examples

function greet(greeting) { return greeting + ", " + this.name; }

const hiAda = myBind(greet, { name: "Ada" }, "Hi");
hiAda(); // "Hi, Ada"
function Point(x, y) { this.x = x; this.y = y; }
Point.prototype.sum = function () { return this.x + this.y; };

const BoundPoint = myBind(Point, null, 1);
const p = new BoundPoint(2);

p.x;                    // 1
p.y;                    // 2
p.sum();                // 3 — prototype methods still work
p instanceof Point;     // true

Under new, the bound receiver is ignored and the fresh object stays on the correct prototype chain.

What it has to do

  • Set this to thisArg for a normal call and prepend boundArgs.
  • Keep the bound receiver even when the bound function is called as another object's method.
  • Under new, ignore thisArg and use the freshly constructed object as this.
  • Under new, keep fn.prototype in the instance's prototype chain so instance instanceof fn holds and prototype methods work.
  • Work when Function.prototype.bind, call and apply have been replaced with throwing stubs.

Notes

  • new.target inside the bound function tells you whether it was called with new. Branch on it to decide whether to use this or thisArg.
  • Point bound.prototype = Object.create(fn.prototype) so instances inherit from fn.prototype. Reach for Reflect.apply instead of .call/.apply — those are the ones the test stubs out.

Stuck? The javascript course covers everything this challenge needs.

Try it yourself
Loading playground...
5 tests · +350 XP

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.