Concepts/JavaScript

call vs apply vs bind

All three set the "this" context of a function. call() and apply() invoke immediately (differing in argument format), while bind() returns a new function for later use.

Side-by-Side Comparison

FeatureFunction.call()Function.apply()Function.bind()
Invokes immediatelyYesYesNo (returns new function)
Argument formatIndividual: fn.call(ctx, a, b)Array: fn.apply(ctx, [a, b])Individual: fn.bind(ctx, a, b)
Partial applicationNoNoYes
ReturnsFunction resultFunction resultNew bound function

Code Examples

Function.call()

  • Invokes the function IMMEDIATELY
  • First argument sets "this"
  • Remaining arguments passed individually
  • fn.call(context, arg1, arg2)
function greet(greeting, punctuation) {
  return `${greeting}, ${this.name}${punctuation}`
}

const user = { name: 'Alice' }
greet.call(user, 'Hello', '!')
// "Hello, Alice!"

Function.apply()

  • Invokes the function IMMEDIATELY
  • First argument sets "this"
  • Second argument is an ARRAY of arguments
  • fn.apply(context, [arg1, arg2])
function greet(greeting, punctuation) {
  return `${greeting}, ${this.name}${punctuation}`
}

const user = { name: 'Alice' }
const args = ['Hello', '!']
greet.apply(user, args)
// "Hello, Alice!"

// Classic use: Math.max with array
Math.max.apply(null, [1, 5, 3]) // 5

Function.bind()

  • Returns a NEW function with "this" permanently set
  • Does NOT invoke immediately
  • Can partially apply arguments (partial application)
  • Returned function can be called later
function greet(greeting, punctuation) {
  return `${greeting}, ${this.name}${punctuation}`
}

const user = { name: 'Alice' }
const greetAlice = greet.bind(user)
greetAlice('Hello', '!') // "Hello, Alice!"

// Partial application
const hiAlice = greet.bind(user, 'Hi')
hiAlice('!') // "Hi, Alice!"

When to Use Which

Function.call()

When you know the arguments and want to invoke immediately. Common for borrowing methods: Array.prototype.slice.call(arguments).

Function.apply()

When arguments are already in an array. Less common since spread syntax arrived: Math.max(...arr) replaces Math.max.apply(null, arr).

Function.bind()

When you need to pass a function with a specific "this" for later invocation — event handlers, callbacks, React class component methods.

Common Mistakes

Interview Questions

How has spread syntax reduced the need for apply()?

Math.max.apply(null, arr) is now Math.max(...arr). Function.apply(ctx, args) is now fn.call(ctx, ...args). Spread syntax is more readable and doesn't require the null context placeholder.

Implement Function.prototype.bind from scratch

Return a wrapper function that uses apply internally: function bind(context, ...boundArgs) { const fn = this; return function(...callArgs) { return fn.apply(context, [...boundArgs, ...callArgs]); }; }

Deep Dive