Using function.bind to Create New Functions
Description
The bind()
function creates a new bound function. Calling the bound function generally results in the execution of the function it wraps, which is also called the target function. The bound function will store the parameters passed - which include the value of this
and the first few arguments - as its internal state. These values are
stored in advance, instead of being passed at call time. You can
generally see const boundFn = fn.bind(thisArg, arg1, arg2)
as being equivalent to const boundFn = (...restArgs) => fn.call(thisArg, arg1, arg2, ...restArgs)
for the effect when it's called (but not when boundFn
is constructed).
A bound function can be further bound by calling boundFn.bind(thisArg, /* more args */)
, which creates another bound function boundFn2
. The newly bound thisArg
value is ignored, because the target function of boundFn2
, which is boundFn
, already has a bound this
. When boundFn2
is called, it would call boundFn
, which in turn calls fn
. The arguments that fn
ultimately receives are, in order: the arguments bound by boundFn
, arguments bound by boundFn2
, and the arguments received by boundFn2
.
"use strict"; // prevent `this` from being boxed into the wrapper object function log(...args) { console.log(this, ...args); } const boundLog = log.bind("this value", 1, 2); const boundLog2 = boundLog.bind("new this value", 3, 4); boundLog2(5, 6); // "this value", 1, 2, 3, 4, 5, 6
A bound function may also be constructed using the new
operator if its target function is constructable. Doing so acts as
though the target function had instead been constructed. The prepended
arguments are provided to the target function as usual, while the
provided this
value is ignored (because construction prepares its own this
, as seen by the parameters of Reflect.construct
). If the bound function is directly constructed, new.target
will be the target function instead. (That is, the bound function is transparent to new.target
).
class Base { constructor(...args) { console.log(new.target === Base); console.log(args); } } const BoundBase = Base.bind(null, 1, 2); new BoundBase(3, 4); // true, [1, 2, 3, 4]
However, because a bound function does not have the prototype
property, it cannot be used as a base class for extends
.
class Derived extends class {}.bind(null) {} // TypeError: Class extends value does not have valid prototype property undefined
When using a bound function as the right-hand side of instanceof
, instanceof
would reach for the target function (which is stored internally in the bound function) and read its prototype
instead.
class Base {} const BoundBase = Base.bind(null, 1, 2); console.log(new Base() instanceof BoundBase); // true
The bound function has the following properties:
length
-
The
length
of the target function minus the number of arguments being bound (not counting thethisArg
parameter), with 0 being the minimum value. name
-
The
name
of the target function plus a"bound "
prefix.
The bound function also inherits the prototype chain of the target function. However, it doesn't have other own properties of the target function (such as static properties if the target function is a class).