CrackFrontendCF
Resources
Practice
CrackFrontend

Your guide to mastering frontend interviews

Resources

LibraryPracticeDonate

Company

About UsContact

Legal

Privacy PolicyTerms of Service

Built with ❀️ by Tushar Khanna

CrackFrontendCF
Resources
Practice

πŸ”— Function.prototype.bind() Polyfill

The bind() method creates a new function with a bound this context and optional preset arguments. Critical for event handlers and callbacks.

Interview Importance: πŸ”΄ Critical β€” One of the holy trinity of , , questions. Understanding demonstrates deep knowledge of JavaScript's binding and closures. -- 1️⃣ What is bind()? creates a new function that, when called, has its keyword set to a specified value, with a given sequence of arguments preceding any provided when the new function is called. Key Characteristics Description New function with bound Modifies original? Yes (can preset arguments) Works as constructor? -- 2️⃣ Why Use bind()? Common Use Cases Problem refers to DOM element lost in callback becomes Need preset arguments Lose context when extracting Real-World Example -- 3️⃣ Native API Signature Description Value to use as inside bound function -- 4️⃣ Implementation Basic Implementation πŸ” Dry Run: Basic Usage -- 5️⃣ Understanding Key Concepts What are and ? Visual: Argument Flow Why Instead of ? -- 6️⃣ Production Implementation (with Support) When a bound function is called with , the bound is ignored: Complete Implementation πŸ” Dry Run: Using with -- 7️⃣ call vs apply vs bind Invokes immediately? Returns Yes Function result Array No New function Aspect Explanation bind() call Just creates a closure Space Stores n bound arguments Bound function call Same as original function call Concept bind() Can preset arguments Returns Bound is ignored Key method Key Takeaways 1. Returns new function β€” doesn't invoke immediately 2. Handle calls β€” check 3. Preserve prototype β€” for proper behavior 4. Combine arguments β€” boundArgs come first 5. Arrow functions ignore bind β€” they have no -- πŸ“š Further Reading MDN: Function.prototype.bind() JavaScript.info: Function binding -- <!-quiz-start --Q1: What does return? [ ] The result of calling the function [x] A new function with bound context [ ] undefined [ ] The original function modified Q2: What happens when you use with a bound function? [ ] An error is thrown [ ] The bound context is used [x] The bound context is ignored and a new object is created [ ] The function returns undefined Q3: What is the effect of calling on an arrow function? [ ] Works exactly like regular functions [ ] Throws a TypeError [x] Has no effect since arrow functions don't have their own [ ] Creates a new arrow function <!-quiz-end --
JavaScriptPolyfills
🎯 Array.prototype.at() Polyfill
medium
βœ… Array.prototype.every() Polyfill
medium
πŸ”² Array.prototype.fill() Polyfill
medium
πŸ” Array.prototype.filter() Polyfill
medium
πŸ”Ž Array.prototype.find() Polyfill
medium
πŸ”’ Array.prototype.findIndex() Polyfill
medium
πŸ”™ Array.prototype.findLast() Polyfill
medium
πŸ”™ Array.prototype.findLastIndex() Polyfill
medium
πŸ“‹ Array.prototype.flat() Polyfill
medium
πŸ” Array.prototype.includes() Polyfill
medium
πŸ”’ Array.prototype.indexOf() Polyfill
medium
βœ… Array.isArray() Polyfill
medium
πŸ—ΊοΈ Array.prototype.map() Polyfill
hard
βž– Array.prototype.pop() Polyfill
medium
βž• Array.prototype.push() Polyfill
easy
πŸ”„ Array.prototype.reduce() Polyfill
medium
πŸ”„ Array.prototype.reverse() Polyfill
hard
⬅️ Array.prototype.shift() Polyfill
hard
πŸ”˜ Array.prototype.some() Polyfill
medium
πŸ”€ Array.prototype.sort() Polyfill
hard
➑️ Array.prototype.unshift() Polyfill
hard
πŸ“ž Function.prototype.apply() Polyfill
medium
πŸ”— Function.prototype.bind() Polyfill
hard
πŸ“ž Function.prototype.call() Polyfill
medium
23 of 24
LibraryJavaScriptPolyfills38 of 61

πŸ”— Function.prototype.bind() Polyfill

jspolyfillshard

Interview Importance: πŸ”΄ Critical β€” One of the holy trinity of call, apply, bind questions. Understanding bind demonstrates deep knowledge of JavaScript's this binding and closures.


1️⃣ What is bind()?

Function.prototype.bind() creates a new function that, when called, has its this keyword set to a specified value, with a given sequence of arguments preceding any provided when the new function is called.

const person = {
  name: 'Alice',
  greet() {
    console.log(`Hello, ${this.name}`);
  }
};

const greet = person.greet;
greet();  // "Hello, undefined" - lost context!

const boundGreet = person.greet.bind(person);
boundGreet();  // "Hello, Alice" - context preserved!

Key Characteristics

FeatureDescription
ReturnsNew function with bound this
Modifies original?No (returns new function)
Partial application?Yes (can preset arguments)
Works as constructor?Yes (bound function can use new)

2️⃣ Why Use bind()?

Common Use Cases

Use CaseProblemSolution with bind
Event handlersthis refers to DOM elementBind to component
Callbacksthis lost in callbackPreserve context
setTimeoutthis becomes windowBind to object
Partial applicationNeed preset argumentsBind arguments
Method extractionLose context when extractingBind before extracting

Real-World Example

class Button {
  constructor(label) {
    this.label = label;
  }

  click() {
    console.log(`Button ${this.label} clicked`);
  }
}

const btn = new Button('Submit');

// ❌ Without bind - loses context
document.addEventListener('click', btn.click);
// Clicking logs: "Button undefined clicked"

// βœ… With bind - preserves context
document.addEventListener('click', btn.click.bind(btn));
// Clicking logs: "Button Submit clicked"

3️⃣ Native API Signature

function.bind(thisArg, arg1, arg2, ...)
ParameterDescription
thisArgValue to use as this inside bound function
arg1, arg2, ...Arguments to prepend to bound function calls (partial application)

4️⃣ Implementation

Basic Implementation

Function.prototype.myBind = function(context, ...boundArgs) {
  // Validate: bind can only be called on functions
  if (typeof this !== 'function') {
    throw new TypeError('myBind must be called on a function');
  }

  // Store reference to original function
  const originalFunction = this;

  // Return new function
  return function(...args) {
    // Combine bound args with new args, call with context
    return originalFunction.apply(context, [...boundArgs, ...args]);
  };
};

πŸ” Dry Run: Basic Usage

function greet(greeting, punctuation) {
  return `${greeting}, ${this.name}${punctuation}`;
}

const person = { name: 'Alice' };
const boundGreet = greet.myBind(person, 'Hello');
boundGreet('!');  // ?
Step 1: greet.myBind(person, 'Hello') is called
---------------------------------------------------------
  this = greet (the function)
  context = { name: 'Alice' }
  boundArgs = ['Hello']
  originalFunction = greet

  Returns: new function(...args) { ... }

Step 2: boundGreet('!') is called
---------------------------------------------------------
  args = ['!']
  Combined args: [...boundArgs, ...args] = ['Hello', '!']

  Calls: originalFunction.apply(context, ['Hello', '!'])
       = greet.apply({ name: 'Alice' }, ['Hello', '!'])

  Inside greet:
    this = { name: 'Alice' }
    greeting = 'Hello'
    punctuation = '!'
    Returns: 'Hello, Alice!'

Output: 'Hello, Alice!'

5️⃣ Understanding Key Concepts

What are boundArgs and args?

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

// Step 1: Bind with preset argument
const addTwo = add.myBind(null, 2);
// boundArgs = [2]

// Step 2: Call with remaining arguments
addTwo(3, 4);
// args = [3, 4]

// Step 3: Combine
// [...boundArgs, ...args] = [2, 3, 4]
// add(2, 3, 4) = 9

Visual: Argument Flow

myBind(context, boundArg1, boundArg2)
                    v          v
              [boundArg1, boundArg2]
                        v
boundFunction(callArg1, callArg2)
                  v         v
                [callArg1, callArg2]
                        v
              [...boundArgs, ...args]
                        v
        [boundArg1, boundArg2, callArg1, callArg2]
                        v
       originalFunction.apply(context, combinedArgs)

Why apply Instead of call?

// apply takes array of arguments
func.apply(context, [arg1, arg2, arg3]);

// call takes arguments separately
func.call(context, arg1, arg2, arg3);

// We have an array [...boundArgs, ...args]
// So apply is more convenient

6️⃣ Production Implementation (with new Support)

When a bound function is called with new, the bound this is ignored:

function Person(name) {
  this.name = name;
}

const BoundPerson = Person.bind({ ignored: true });
const p = new BoundPerson('Alice');
console.log(p.name);      // 'Alice'
console.log(p.ignored);   // undefined - bound context ignored!

Complete Implementation

Function.prototype.myBind = function(context, ...boundArgs) {
  if (typeof this !== 'function') {
    throw new TypeError('Bind must be called on a function');
  }

  const originalFunction = this;

  // Named function for constructor support
  function boundFunction(...args) {
    // Check if called with 'new'
    const isNewCall = this instanceof boundFunction;

    return originalFunction.apply(
      // If 'new', use newly created object; otherwise use bound context
      isNewCall ? this : context,
      [...boundArgs, ...args]
    );
  }

  // Preserve prototype chain for 'new' calls
  if (originalFunction.prototype) {
    boundFunction.prototype = Object.create(originalFunction.prototype);
  }

  return boundFunction;
};

πŸ” Dry Run: Using with new

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const BoundPerson = Person.myBind({ ignored: true }, 'Alice');
const p = new BoundPerson(25);
Step 1: Person.myBind({ ignored: true }, 'Alice')
---------------------------------------------------------
  originalFunction = Person
  context = { ignored: true }
  boundArgs = ['Alice']

  Creates boundFunction with:
    boundFunction.prototype = Object.create(Person.prototype)

  Returns: boundFunction

Step 2: new BoundPerson(25)
---------------------------------------------------------
  JavaScript creates new object: newObj = {}
  Sets: newObj.__proto__ = boundFunction.prototype

  Calls boundFunction with this = newObj:
    isNewCall = newObj instanceof boundFunction -> true
    args = [25]
    combinedArgs = ['Alice', 25]

    Calls: Person.apply(newObj, ['Alice', 25])

    Inside Person:
      this = newObj
      this.name = 'Alice'
      this.age = 25

    newObj is now { name: 'Alice', age: 25 }

Step 3: Result
---------------------------------------------------------
  p = { name: 'Alice', age: 25 }
  p instanceof Person -> true (prototype chain preserved)
  p instanceof BoundPerson -> true

7️⃣ call vs apply vs bind

MethodInvokes immediately?Arguments formatReturns
callYesComma separatedFunction result
applyYesArrayFunction result
bindNoComma separatedNew function
const obj = { x: 10 };

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

// call - immediate, separate args
add.call(obj, 1, 2);     // 13

// apply - immediate, array args
add.apply(obj, [1, 2]);  // 13

// bind - returns new function
const bound = add.bind(obj, 1);
bound(2);                // 13

Memory Aid

call   -> Comma separated, Calls immediately
apply  -> Array of arguments, Applies immediately
bind   -> Binds context, returns Bound function

8️⃣ Common Interview Questions

Q1: Implement bind from scratch

Answer: See Section 4 for basic, Section 6 for production.

Q2: What's the difference between call, apply, and bind?

Answer:

  • call: Immediately invokes with comma-separated args
  • apply: Immediately invokes with array of args
  • bind: Returns new function, doesn't invoke

Q3: Can you bind an already-bound function?

Answer: Yes, but only the first bound context applies:

function log() {
  console.log(this.x);
}

const bound1 = log.bind({ x: 1 });
const bound2 = bound1.bind({ x: 2 });

bound2();  // 1 (first bind wins!)

Q4: What happens when you use bind with arrow functions?

Answer: Arrow functions ignore bind because they don't have their own this:

const arrow = () => console.log(this.x);
const bound = arrow.bind({ x: 10 });

bound();  // undefined (or window.x) - bind has no effect!

Q5: How would you polyfill bind without using apply or call?

Answer:

Function.prototype.myBind = function(context, ...boundArgs) {
  const fn = this;

  return function(...args) {
    // Temporarily add function to context
    const key = Symbol('fn');
    context[key] = fn;

    // Call as method
    const result = context[key](...boundArgs, ...args);

    // Cleanup
    delete context[key];

    return result;
  };
};

Q6: Why do we need to preserve the prototype?

Answer: For instanceof checks and prototype chain inheritance:

function Foo() {}
const BoundFoo = Foo.myBind(null);

const instance = new BoundFoo();

// Without prototype preservation:
instance instanceof Foo;  // false (wrong!)

// With prototype preservation:
instance instanceof Foo;  // true (correct!)

9️⃣ Common Pitfalls

Pitfall 1: Forgetting this Check

// ❌ BAD: Doesn't validate this is a function
Function.prototype.badBind = function(context) {
  const fn = this;  // Could be anything!
  return function() {
    return fn.apply(context);
  };
};

// Calling on non-function crashes later
const obj = {};
// obj.badBind({});  // Would fail when returned function is called

// βœ… GOOD: Validate this
Function.prototype.goodBind = function(context) {
  if (typeof this !== 'function') {
    throw new TypeError('Must be called on a function');
  }
  // ...
};

Pitfall 2: Not Handling new Calls

// ❌ BAD: Ignores new calls
Function.prototype.badBind = function(context) {
  const fn = this;
  return function(...args) {
    return fn.apply(context, args);  // Always uses context
  };
};

function Person(name) { this.name = name; }
const BoundPerson = Person.badBind({ x: 1 });
const p = new BoundPerson('Alice');
console.log(p.name);  // undefined! (context was { x: 1 })

// βœ… GOOD: Check for new call
Function.prototype.goodBind = function(context) {
  const fn = this;
  function bound(...args) {
    return fn.apply(
      this instanceof bound ? this : context,
      args
    );
  }
  bound.prototype = Object.create(fn.prototype);
  return bound;
};

Pitfall 3: Using Arrow Function for Return

// ❌ BAD: Arrow function - can't use 'new', no 'this' binding check
Function.prototype.badBind = function(context) {
  const fn = this;
  return (...args) => fn.apply(context, args);
};

// Can't use with new:
const Bound = function Foo(){}.badBind(null);
// new Bound();  // TypeError: Bound is not a constructor

// βœ… GOOD: Use regular function
Function.prototype.goodBind = function(context) {
  const fn = this;
  return function(...args) {  // Regular function
    return fn.apply(context, args);
  };
};

Pitfall 4: Not Preserving Prototype

// ❌ BAD: Loses prototype chain
Function.prototype.badBind = function(context) {
  const fn = this;
  return function bound(...args) {
    return fn.apply(this instanceof bound ? this : context, args);
  };
  // Missing: bound.prototype = ...
};

// βœ… GOOD: Preserve prototype
Function.prototype.goodBind = function(context) {
  const fn = this;
  function bound(...args) {
    return fn.apply(this instanceof bound ? this : context, args);
  }
  if (fn.prototype) {
    bound.prototype = Object.create(fn.prototype);
  }
  return bound;
};

πŸ”Ÿ Time & Space Complexity

AspectComplexityExplanation
bind() callO(1)Just creates a closure
SpaceO(n)Stores n bound arguments
Bound function callO(1)Same as original function call

Summary

ConceptDescription
bind()Creates new function with bound this
Partial applicationCan preset arguments
ReturnsNew function (doesn't invoke)
new behaviorBound this is ignored
Key methodapply() or call() internally

Key Takeaways

  1. Returns new function β€” doesn't invoke immediately
  2. Handle new calls β€” check this instanceof boundFunction
  3. Preserve prototype β€” for proper instanceof behavior
  4. Combine arguments β€” boundArgs come first
  5. Arrow functions ignore bind β€” they have no this

πŸ“š Further Reading

  • MDN: Function.prototype.bind()
  • JavaScript.info: Function binding

Quick Quiz

Test your understanding with 3 quick questions

Q1What does `bind()` return?
Q2What happens when you use `new` with a bound function?
Q3What is the effect of calling `bind()` on an arrow function?

Continue Reading

CrackFrontend

Your guide to mastering frontend interviews

Resources

LibraryPracticeDonate

Company

About UsContact

Legal

Privacy PolicyTerms of Service

Built with ❀️ by Tushar Khanna