Function.prototype.bind()

Creates a new function with this permanently fixed and any leading arguments pre-filled.

Signature
bind(thisArg)
bind(thisArg, arg1)
bind(thisArg, arg1, arg2)
bind(thisArg, arg1, arg2, /* …, */ argN)
  • Added in JavaScript ECMAScript 5 (2009)

Parameters

ParameterTypeDescription
$thisArganyThe value to be passed as the this parameter to the target function when the bound function is called. If the function is not in strict mode, null and undefined are replaced with the global object, and primitive values are converted to objects. The value is ignored if the bound function is constructed using new.
$arg1, …, argNoptionalanyArguments to prepend to the arguments provided to the bound function when invoking the target function.

Return value

FunctionA copy of the given function with the specified this value, and initial arguments (if provided).

Errors

Throws a TypeError if the value it is called on is not callable.

Changelog

  • PHP ECMAScript 2015The bound function's name is specified as the target's name with a "bound " prefix, and its length is the target's length minus the number of pre-filled arguments, floored at 0.
  • PHP ECMAScript 2015Bound functions do not have their own prototype property, but remain constructable when the target is; the thisArg is discarded under new.

bind() does not call anything. It returns a new function that, however it is later invoked, runs the original with the this you fixed and any arguments you pre-filled prepended to whatever the caller passes.

When to reach for it

  • Handing a method to something that will call it plainly — a callback, a timer, an event listener. Detached methods lose their receiver; a bound copy keeps it.
  • Partial application. log.bind(null, "WARN") gives you a warn() that needs only the message.
  • Building a reusable extracted method, such as const has = Object.prototype.hasOwnProperty.bind(obj).

What trips people up

Binding is permanent and one-shot. Re-binding an already-bound function does nothing — the inner binding wins, and call() and apply() on a bound function cannot override this either.

Every call returns a fresh function object. fn.bind(o) !== fn.bind(o), so binding inline inside a listener registration means you can never remove that listener. Bind once and store the result.

The returned function reports a name of "bound " + original.name and a reduced length, and it has no own prototype property, though new on it still works when the target is a constructor.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Pass a class method as a callback without it losing its instance
  • Pre-fill a logger's level so callers only supply the message
  • Extract a built-in prototype method into a standalone helper
  • Freeze a partially applied constructor, such as a Point with x pinned to 0

Frequently asked questions

What is the difference between bind() and call()?

bind() returns a new function for later use, while call() invokes the function immediately. Use bind() when you are handing the function to someone else — a callback, a timer, an event listener — and call() when you want the result right now.

Why doesn't bind() work a second time?

Because the first bind() produces an exotic bound function whose receiver is baked in; a second bind(), and call() or apply() on it, cannot change it. If you need a different this, bind the original target function again rather than the bound copy.

Should I use bind() or a class field arrow function?

A class field arrow (handle = () => {...}) is the common modern choice for auto-bound handlers, since it is created per instance with lexical this and needs no constructor wiring. bind() is still the right tool for partial application and for binding a function you did not write.

More examples

Binding happens once and cannot be undone

Re-binding is a no-op: second() still reports "first", and call() cannot override the bound receiver either. The last line prints false, which is why an inline .bind() inside addEventListener leaves you with a listener you cannot remove.

Example · javascript
function who() {
  return this.id;
}
const first = who.bind({ id: "first" });
const second = first.bind({ id: "second" });

console.log(first(), second());
console.log(first.call({ id: "ignored" }));

// Each bind() allocates a distinct function object
const target = { id: "x" };
console.log(who.bind(target) === who.bind(target));

Bound functions under new

Under new the bound thisArg (null) is discarded and a fresh object is constructed, but the pre-filled 0 still applies, so p is {x: 0, y: 5} and instanceof Point holds. YAxis has no own prototype property yet remains constructable, and its length dropped from 2 to 1.

Example · javascript
function Point(x, y) {
  this.x = x;
  this.y = y;
}
const YAxis = Point.bind(null, 0); // x is always 0

const p = new YAxis(5);
console.log(p.x, p.y);
console.log(p instanceof Point);

// The bound function has no own prototype property
console.log(Object.hasOwn(YAxis, "prototype"));
console.log(YAxis.name, YAxis.length);

Discussion

  • Be the first to comment on this lesson.