Pass Functions into Other Functions
Besides calling functions from inside of other functions, we can also pass functions
into other functions and store them in parameters.
Why would we want to do that? Well, when we define function
a()
to call function
b()
,
we are hardcoding function
a()
to call function
b()
.
Most of the time, that's what we want. But sometimes we want function
a()
to a call a function to be determined later.
In this example, we define the
drawPlate()
function, which has three parameters:
function drawPlate(x, y, drawFood) {
context.save();
context.fillStyle = '#FFFFFF';
context.strokeStyle = '#999999';
context.fillRect(x - 120, y - 20, 240, 20);
context.strokeRect(x - 120, y - 20, 240, 20);
context.restore();
if (drawFood === undefined) {
return;
}
drawFood(x, y - 20);
}
The parameters
x
and
y
are the coordinates of the bottom center point of the plate. We draw a white
rectangle with a gray outline centered at
x
and sitting on top of
y
.
Then, we do something odd. We check if the parameter
drawFood
is
undefined
.
If a variable is undefined, it means a value was never assigned to it. If that's the
case here, we are going to end the function with a return statement. There are
other ways we could have done this, but we wanted to show you how to end a function early.
If
drawFood
is not undefined, then we call it as a function. Notice the parentheses () after the
parameter name. We are calling it as a function and passing it the coordinates of the top
center point of the plate. This is where we want the food drawn on the plate to be positioned.
To draw a sandwich on top of a plate, we have refactored the
drawSandwich()
function so it now draws the sandwich centered at the parameter
x
and on top of
y
.
function drawSandwich(x, y) {
context.save();
drawBread(x - 100, y - 110);
drawRoastBeef(x - 90, y - 80);
drawCheeseSlice(x - 100, y - 68);
drawCheeseSlice(x - 100, y - 50);
drawBread(x -100, y - 30);
context.restore();
}
To draw a piece of cake on top of a plate, we have defined the
drawCake()
function:
function drawCake(x, y) {
context.save();
context.fillStyle = '#FFFF00';
context.fillRect(x - 90, y - 180, 180, 180);
context.fillStyle = '#CD853F';
context.fillRect(x - 90, y - 8, 180, 8);
context.fillRect(x - 90, y - 51, 180, 8);
context.fillRect(x - 90, y - 94, 180, 8);
context.fillRect(x - 90, y - 137, 180, 8);
context.fillRect(x - 90, y - 180, 180, 8);
context.fillRect(x - 90, y - 180, 8, 180);
context.restore();
}
Putting everything together, we draw one plate with a piece of cake and one
plate with a sandwich by calling:
drawPlate(140, 240, drawCake);
drawPlate(400, 240, drawSandwich);
Note that we are passing the name of the
drawCake()
or
drawSandwich()
function without putting parentheses () after them. We use parentheses to call
a function. Here we are treating the function name as a variable that we are passing
into the
drawPlate()
function to be called later. If we don't pass in a function at all, the plate will
be drawn empty.
When we call the
drawCake()
or
drawSandwich()
functions inside of the
drawPlate()
function after passing them into the function as arguments, they behave as local functions
that have been declared inside of the
drawPlate()
function, not as global functions. This means they have access to the local variables
declared inside of the
drawPlate()
function.
Quick Reference:
Coordinates
Variables
fillRect()
fillStyle
save() / restore()