With the ES6 spread operator (
...
), we can accomplish the same result as
apply
. In
the instance of our
update
method, where we do care about the
this
value, we still
have to use
call
, but for
Math.min
and
Math.max
, where it doesn’t matter, we can use
the spread operator to call these functions directly:
const
newBruce
=
[
1940
,
"martial artist"
];
update
.
call
(
bruce
,
...
newBruce
);
// equivalent to apply(bruce, newBruce)
Math
.
min
(
...
arr
);
// -5
Math
.
max
(
...
arr
);
// 15
There’s one final function that allows you to specify the value for
this
:
bind
.
bind
allows you to permanently associate a value for
this
with a function. Imagine we’re
passing our
update
method around, and we want to make sure that it always gets
called with
bruce
as the value for
this
, no matter how it’s called (even with
call
,
apply
, or another
bind
).
bind
allows us to do that:
const
updateBruce
=
update
.
bind
(
bruce
);
updateBruce
(
1904
,
"actor"
);
// bruce is now { name: "Bruce", birthYear: 1904, occupation: "actor" }
updateBruce
.
call
(
madeline
,
1274
,
"king"
);
// bruce is now { name: "Bruce", birthYear: 1274, occupation: "king" };
// madeline is unchanged
The fact that the action of
bind
is permanent makes it potentially a source of difficult-
to-find bugs: in essence, you are left with a function that cannot be used effectively
with
call
,
apply
, or
bind
(a second time). Imagine passing around a function that
gets invoked with
call
or
apply
in some distant location, fully expecting
this
to get
bound accordingly. I’m not suggesting that you avoid the use of
bind
; it’s quite useful,
but be mindful of the way bound functions will be used.
You can also provide parameters to
bind
, which has the effect of creating a new func‐
tion that’s always invoked with specific parameters. For example, if you wanted an
update
function that always set the birth year of
bruce
to
1949
, but still allowed you
to change the occupation, you could do this:
const
updateBruce1949
=
update
.
bind
(
bruce
,
1949
);
updateBruce1949
(
"singer, songwriter"
);
// bruce is now { name: "Bruce", birthYear: 1949,
// occupation: "singer, songwriter" }
Conclusion
Functions are a vital part of JavaScript. They do far more than just modularize code:
they allow for the construction of incredibly powerful algorithmic units. This chapter
has mainly been about the mechanics of functions—a dry but important introduc‐
tion. Armed with this foundation, we’ll see the power of functions unlocked in com‐
ing chapters.
116 | Chapter 6: Functions