Function.prototype.bind Polyfill
Implement Function.prototype.myBind.
Function Signature:
Function.prototype.myBind = function (context, ...boundArgs) { }
Requirements:
- Return a new function — do not invoke immediately
- Pre-fill
boundArgs(partial application); merge with call-time args - When the returned function is called with
new, ignore the bound context and use the new instance instead - Preserve the prototype chain so
instanceofworks correctly on new instances
Examples
function greet(greeting, punct) { return greeting + ' ' + this.name + punct; }
const greetAlice = greet.myBind({ name: 'Alice' }, 'Hello');
greetAlice('!')'Hello Alice!'function Point(x, y) { this.x = x; this.y = y; }
const BoundPoint = Point.myBind(null, 10);
const p = new BoundPoint(20);
console.log(p.x, p.y);10 20Constraints
- Implement the basic version first, then add the `new` handling
Notes
- `this instanceof boundFn` is true when called with new — use that to detect the constructor case
- Set `boundFn.prototype = Object.create(originalFn.prototype)` to preserve the chain
Hints
Editorial: Function.prototype.bind Polyfill
Implementing Function.prototype.bind from scratch
bind returns a new function with this permanently fixed and optional arguments pre-filled. It does not invoke immediately. This is the hardest of the three function prototype polyfills.
What the interviewer checks
The detail almost nobody gets: if the bound function is later called with new, the bound this is ignored and the freshly created instance is used instead. The prototype chain must still work so instanceof passes.
Implementation
Function.prototype.myBind = function (context, ...boundArgs) { const originalFn = this; function boundFn(...callArgs) { // when called with `new`, `this instanceof boundFn` is true, // so we ignore the bound context and use the new instance const calledWithNew = this instanceof boundFn; return originalFn.apply( calledWithNew ? this : context, [...boundArgs, ...callArgs] ); } // preserve the prototype chain so `new` produces correct instances if (originalFn.prototype) { boundFn.prototype = Object.create(originalFn.prototype); } return boundFn; };
Partial application
bind supports pre-filling arguments (partial application). Arguments supplied at bind time are merged with arguments supplied at call time:
function add(a, b, c) { return a + b + c; } const addFive = add.myBind(null, 5); addFive(3, 2); // 10 → 5 + 3 + 2
The new operator case
function Point(x, y) { this.x = x; this.y = y; } const BoundPoint = Point.myBind(null, 10); const p = new BoundPoint(20); // p.x === 10, p.y === 20 // The null context is ignored; `this` is the new instance
this instanceof boundFn is true when called with new because new sets up the prototype chain first.
Interview strategy
Write the simple version first (without new handling), then say: "To fully match the spec I'd also handle the constructor case" and add it. Interviewers reward seeing you prioritize and layer complexity.
Edge cases to mention
- The returned function is not the original —
myBindreturnsboundFn boundFn.lengthwon't matchoriginalFn.length(a spec detail, usually fine to skip)- If
originalFn.prototypeisnullorundefined, skip the prototype assignment