Useful Cheatsheetsusefulcheatsheets.com
JavaScript Call Apply Bind
Chapter 26 · Page 206
Advanced

JavaScript Call Apply Bind

Control the this keyword explicitly using call, apply, and bind on any function.

TL;DR

  1. 01call() and apply() invoke a function with a chosen this value.
  2. 02apply() takes arguments as an array; call() takes a list.
  3. 03bind() returns a new function with this permanently fixed.

Tips

  1. 01Use bind() when passing a method as a callback or event handler, so this stays correct.
  2. 02Reach for apply() when arguments already exist as an array, such as forwarding arguments between wrapper functions.

Warnings

  1. 01Calling bind() repeatedly on the same function creates a new wrapper each time, which breaks reference equality checks like removeEventListener.
  2. 02Arrow functions ignore call, apply, and bind for this, since arrow functions always inherit this from their enclosing scope.
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Call Apply Bind
Chapter 26 · Page 207
Advanced

JavaScript Call Apply Bind

(continued)

Why this Needs Explicit Control

  • Call site matters

    The value of this depends on how a function is called, not where it's defined.

    const user = { name: 'Ada', greet() { return `Hi, ${this.name}`; } };
    const fn = user.greet;
    fn(); // 'Hi, undefined' — this lost its connection to user
  • Detached methods

    Passing a method as a value, like a callback, detaches it from its original object.

  • Explicit control

    call, apply, and bind exist to set this explicitly regardless of call site.

  • Function.prototype

    All three live on Function.prototype, so every function has access to them.

  • Common breakage

    Without explicit control, callbacks and event handlers commonly break on this.

  • Legacy code

    Understanding these three methods is essential for working with older, non-arrow-function code.

Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Call Apply Bind
Chapter 26 · Page 208
Advanced

JavaScript Call Apply Bind

(continued)

Using call()

  • call(thisArg, ...args)

    Invoke a function immediately with arguments listed individually.

    function greet(greeting) { return `${greeting}, ${this.name}`; }
    greet.call({ name: 'Ada' }, 'Hi'); // 'Hi, Ada'
  • First argument is this

    The first argument becomes this inside the function for that one call.

  • Positional arguments

    Remaining arguments map positionally to the function's parameters.

  • Borrowing methods

    Use call() to borrow a method from one object and run it against another.

    const max = Math.max.call(null, 1, 5, 3); // 5
  • null or undefined

    Passing null or undefined as thisArg uses the global object in non-strict mode.

  • Single invocation only

    call() does not change the original function; it only affects that single invocation.

Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Call Apply Bind
Chapter 26 · Page 209
Advanced

JavaScript Call Apply Bind

(continued)

Using apply()

  • apply(thisArg, argsArray)

    Works exactly like call(), but arguments are passed as one array.

    function sum(a, b, c) { return a + b + c; }
    sum.apply(null, [1, 2, 3]); // 6
  • Array-like arguments

    apply() is the better choice when arguments already exist as an array or array-like.

    Math.max.apply(null, [4, 8, 2]); // 8
  • Spread replaces it

    Modern code often replaces apply() with the spread operator: Math.max(...nums).

  • Forwarding arguments

    apply() still matters when forwarding an arguments object between functions.

  • Synchronous return

    Both call() and apply() execute the function synchronously and return its result.

  • Choosing between them

    Choosing between call and apply is purely about argument shape — list versus array.

Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Call Apply Bind
Chapter 26 · Page 210
Advanced

JavaScript Call Apply Bind

(continued)

Using bind()

  • bind(thisArg)

    Creates a new function with this permanently fixed to the given value.

    const user = { name: 'Ada', greet() { return `Hi, ${this.name}`; } };
    const boundGreet = user.greet.bind(user);
    boundGreet(); // 'Hi, Ada' — works even detached from user
  • Doesn't invoke

    Unlike call() and apply(), bind() does not invoke the function immediately.

  • Store for later

    The returned function can be stored, passed around, and called later safely.

  • Bind in constructors

    Bind methods in a constructor so they keep this when used as callbacks.

    class Button {
      constructor() { this.onClick = this.onClick.bind(this); }
      onClick() { console.log(this); }
    }
  • Fixed permanently

    Calling bind() again on an already-bound function cannot change its fixed this.

  • Bound function names

    Bound functions report 'bound functionName' when inspected, which helps when debugging.

Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Call Apply Bind
Chapter 26 · Page 211
Advanced

JavaScript Call Apply Bind

(continued)

Partial Application with bind

  • Prepended arguments

    Arguments passed to bind() after thisArg get permanently prepended to every future call.

    function multiply(a, b) { return a * b; }
    const double = multiply.bind(null, 2);
    double(5); // 10
  • Partial application

    This technique is called partial application, fixing some arguments ahead of time.

  • Event handler context

    Combine partial application with event handlers to pass extra context cleanly.

    button.addEventListener('click', handleClick.bind(null, itemId));
  • Extra arguments still work

    Partially applied functions still accept additional arguments at call time.

  • Specialized utilities

    Use partial application to build specialized utility functions from general ones.

  • Avoids wrappers

    This pattern avoids writing repetitive wrapper functions for common argument combinations.

Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Call Apply Bind
Chapter 26 · Page 212
Advanced

JavaScript Call Apply Bind

(FAQ)

FAQ

Both invoke a function immediately with a specified this value. call() takes the function's arguments individually, separated by commas. apply() takes them bundled into a single array. They behave identically once the arguments are in place.

call() and apply() invoke the function right away. bind() does not call the function; it returns a new function with this permanently set. You call that returned function later, optionally with more arguments.

When a method is passed as a callback, like onClick={this.handleClick}, it loses its connection to the instance. Calling it later sets this to undefined or the global object instead of the instance. Binding it in the constructor, or using an arrow function class field, fixes this permanently.

Yes, this is called partial application. Any arguments passed to bind() after the this value get permanently prepended to future calls. For example, multiply.bind(null, 2) returns a function that always doubles its input.

Calling bind() on an arrow function has no effect on this, because arrow functions never have their own this. You can still bind arguments for partial application, but the this value stays whatever it was lexically. Use a regular function if you need bind() to control this.

Useful Cheatsheetsusefulcheatsheets.com
JavaScript Call Apply Bind
Chapter 26 · Page 213
Advanced

JavaScript Call Apply Bind

(In Practice)
In Practice

Formatting Log Messages with call() and bind()

call() borrows a shared formatter for different log entries, while bind() creates reusable, prefixed logger functions.

  1. 01format() reads this.level and this.message, so call() supplies a different object as this each time.
  2. 02Passing 'API' as the second call() argument fills the prefix parameter for that one invocation.
  3. 03log.bind(null, 'API') permanently fixes the prefix argument, returning a reusable specialized function.
  4. 04apiLog can still be called later with the remaining level and message arguments.
function format(prefix) {
  return `[${prefix}] ${this.level}: ${this.message}`;
}

const errorEntry = { level: 'ERROR', message: 'Connection lost' };
const infoEntry = { level: 'INFO', message: 'Server started' };

console.log(format.call(errorEntry, 'API')); // '[API] ERROR: Connection lost'
console.log(format.call(infoEntry, 'API'));  // '[API] INFO: Server started'

function log(prefix, level, message) {
  console.log(`[${prefix}] ${level}: ${message}`);
}

const apiLog = log.bind(null, 'API');
apiLog('WARN', 'Rate limit approaching');
// '[API] WARN: Rate limit approaching'
Takeaway

call() sets this for a single invocation, while bind() locks in this and arguments for reuse.