call, apply & bind
Three ways to set this by hand -- invoke now with args, invoke now with an array, or make a permanently-bound copy.
Syntax
fn.call(thisArg, a, b)
fn.apply(thisArg, [a, b])
const g = fn.bind(thisArg, a)Every function inherits these three from Function.prototype. They all set this explicitly; they differ in when and how arguments arrive.
| Method | Calls now? | Arguments |
|---|---|---|
call | yes | listed one by one |
apply | yes | a single array |
bind | no -- returns a new fn | optionally pre-filled |
greet.call(user, 'Hi');
greet.apply(user, ['Hi']);
const boundGreet = greet.bind(user); // reusable, this locked to userbind also does partial application
Arguments you pass to bind are pre-set on the new function, so const add5 = add.bind(null, 5) is a one-liner partial. And a bound function can never be re-bound -- its this is sealed.
Example
Loading editor…
Press Run to execute the code.
When to use it
- Use bind to pre-set this on a class method before registering it as a DOM event listener.
- Use apply to forward a variadic array of arguments to a function that expects individual parameters.
- Use call to invoke a superclass method from a subclass override.
More examples
call with explicit this
call invokes total with order as this so this.prices resolves to order.prices.
function total() {
return this.prices.reduce((s, p) => s + p, 0);
}
const order = { prices: [10, 25, 5] };
console.log(total.call(order)); // 40apply with argument array
apply spreads the args array as individual positional arguments, equivalent to log(...args).
function log(level, source, message) {
console.log(`[${level}] (${source}) ${message}`);
}
const args = ["ERROR", "db.js", "Connection refused"];
log.apply(null, args);bind for stable event handler
bind permanently fixes this to the btn instance so handleClick works correctly as a DOM event listener.
class Button {
constructor(label) { this.label = label; }
handleClick() { console.log("Clicked:", this.label); }
}
const btn = new Button("Submit");
const handler = btn.handleClick.bind(btn);
document.querySelector("button")?.addEventListener("click", handler);
Discussion