-: Now that we have learned a lot of new stuff
about objects, let's switch to another topic.
Functions.
Actually, it's not a completely unrelated topic,
because we already know that functions are also objects.
That being said, it makes sense that with functions
we can do the same things that we can do with objects.
So let's see some facts about functions.
First, as we already know,
a function is an instance
of the object type,
and because of that, a function behaves
like any other object.
We can store functions in a variable,
and we already know that
we can pass a function
as an argument to another function.
We can also return a function from a function.
Because of all that, we say that in JavaScript
we have first class functions.
So let's see a real-world example
of how functions can accept other functions
as arguments.
Actually, we already did this.
Do you remember the picking project
that we coded before?
We set up some event listeners back then, right?
We passed a function into each one of them,
in order to handle each event.
Back then we already used first-class functions,
but we didn't just know it.
All right, so let's now imagine
that we have a couple of arrays
filled with values and that we wanted
to do some calculations with them,
and a birth year array
could be a good example of this.
Let's write an array with some years in it.
So, 1990,
1965,
1937.
I'm just going to write five numbers here,
so five years.
2005, and 1998.
All right, so five years.
Remember we want to do some calculations
with these values, or based on these values.
Now, we could do a huge function
which does all of these calculations
that we want to perform at the same time,
it then resolves all the result arrays
at the same time,
but that would not be
really good practice because instead,
we can write a function that will receive an array
and return a new result array,
and do the calculations based
on a function that we pass into
the calculation function.
So, let's write that calculation function
and call it arrayCalc.
So, function arrayCalc,
and what we're gonna pass
in here is the array, which will be, for example,
the years array, and then we will pass a function
which does the actual calculations.
So, let's see what this function does.
In here, we will simply loop over the array,
and return a result.
The first thing is to create a new, empty array
which will be the one that we're gonna fill
and then return,
so var arr for the result,
so I'm just going to say Res here,
and it's an empty array.
All right, and do you remember
how we loop over arrays?
We've always been doing it
using the "for" loop, right?
So, let's continue doing it this way.
We set up a new variable, i, which is our counter.
Set it to zero and then loop,
as long as i is smaller
than the length of the array that we input, right?
By now you already know
how this length property works, right?
Then after each loop,
we increment our counter by 1.
Okay, down here, inside of the loop,
we will then use the function
that we can pass into this function.
We will push something into our result array here,
we can do it like this,
we use the push function,
or the push method, to be correct,
which, as you remember, inserts an element
at the end of an array.
So the big question here is,
"What are we actually going to push into the array?"
The answer is that it will be the result
of calling or fn function,
so fn,
and then we pass the current element of
our input array into this function.
Array i,
okay?
This will make a lot more sense after you see
one of the functions that we're going to program next,
so I will explain it a little bit better by then.
Now, all we have to is to actually return
this result array.
So, return, of course, arrRes.
Let's now quickly write one of the functions
that we can then later use
here as our fn function.
We will write a couple of simple functions
that do only one single task,
and these functions will actually be called
"callback" functions,
because they are functions that we pass
into functions that will then call them later.
In this case, our callback function, fn,
will be called here when we want to push
a new element into our array.
Let's now write one of these functions,
and it will be our well-known calculate age function.
Let's do it like this, function calculateAge.
At this time I'm simply gonna call it "el",
which stands for element, and we're gonna return
2016 minus the element.
This was usually called our year-of-birth parameter,
but this time we're simply gonna call it "el".
This is one of these simple functions.
You see, it only has one task.
It receives this "el" argument,
and then returns the age based on that argument.
So, really simple.
Now, our arrayCalc function can make a lot more sense.
Let's see what happens here.
Again, we have our empty array here,
and then we start looping through the array
that we input, which is, for example,
this array here with all of these birth years.
When we're done, hit this line in code here,
what's going to happen is that our callback function,
fn, will be called with the i element
of the input array.
Imagine in the first loop i is zero.
So with this arr[i], we're going to retrieve
the first value of the years array, so 1990,
and then we'll push this 1990 into the fn function,
which will be calculateAge, right?
Then this function does it's work and it returns
2016 minus 1990 in this case,
and then the result will simply get pushed
into the array, and after this is completed
five times, then the result will be returned.
Let's do some practice and actually call
the arrayCalc function.
So, arrayCalc
with our years
and calculateAge
as the callback function.
Again, I'm not going to call the function right here,
because this way I would need the parentheses,
like this, but that's not what we want.
We don't want to call a function here,
we want it to be called later by the arrayCalc function.
That's why it's called a callback function,
because it's called later.
We simply pass this variable which is this function
right into this other function.
Now we just have to store this into a variable,
because the other way we cannot really see it.
I'm going to call it "ages",
then we just need to put the correct name here,
and then let's console.log this array.
Ages.
Let's see if this works.
We have a small bug here, in line 109.
You see?
Line 109 and here I see the error,
it's not a comma, it's a semi-colon.
Let's try it again.
Now we have our ages, so this actually worked.
Our arrayCalc function looped through the years array
five times, and five times the calculateAge function here
was called and then pushed the result right into the array
that we then returned.
Again, we can imagine this function as a generic machine
that loops through an array
and we can tell that machine what to do
with each element in the array.
That's what we do with our fn parameter,
which is to callback.
Let's now write another callback function,
so that you can really see how powerful
this pattern can be.
Let's now write a function which can determine
if someone is of full age.
So, function,
isfullAge,
and again,
we're going to receive an element simply here.
We just use a very generic parameter name here.
This time we're simply going to return
if the element is greater or equal to 18, right?
We simply want to return a true or false value,
and that's what this comparison operator here returns.
So if the element is greater or equal to 18,
it will be true, otherwise it will be false.
Let's test this one as well, down here,
and this one I'm going to call fullAges.
Then again we use our generic function,
which I like to think of as a machine,
that then we can use as an input the ages array,
that we calculated before.
Then this time we pass the isFullAge function
into our generic calculation function.
Now I want to log the fullAges as well.
Console.log, fullAges.
Let's see this.
All right!
This makes sense.
The only one here that's actually younger than 18
is this one, and so this one is the only one
with false.
Right?
Everything is working just fine.
As a third example, I have a really cool one,
which is the maximum heart rate,
and that is the highest rate measured in beats per minute
that a person can reach when exercising.
It's calculated based on the age of the person,
so it's a great fit for this example here.
I thought this would be a really cool use case
for people who like to work out.
Let's see this formula and let's see how to use this.
So, function and maxHeartRate.
Again, we're using simply an element as the input
and the formula is actually really simple,
so return 206.9 minus 0.67 x the age.
The age will be the element, so we will always call
our arrayCalc function here with the age as the input,
so not with the years, but with the age.
Now we also want this to be an integer,
so we want to return a value here that is not a decimal.
Let's do that.
I'm sure that you remember the math object,
and we used the ceiling method before,
or the floor method, I don't remember,
but now we're going to use the round.
What round does is very simple,
it simply rounds the number to the closest integer.
So, very simple.
Now, only one thing left in this function here,
is that this formula is actually only valid
for people between 18 and 81 in ages.
So, you already know how to do that, right?
We use an if el statement,
so if the element is
greater or equal to 18, and,
at the same time,
less than or even equal or less than 81.
In this case we want to return this,
and if the person's all of these ranges,
then we simply return minus 1.
That's it.
That's our function for the maxHeartRate.
Once again, let's now use this.
Let's just call this rates and then arrayCalc.
Again, we're using the ages as an input,
and then our callback function is the maxHeartRate.
Now instead of the fullAges, I want to log the rates.
Okay.
So here are the calculated heart rate,
maximum heart rate, which is only minus 1
for this person here and that's because it's clearly
a younger than 18.
Let's think again about what we did here.
So, we created a generic function which loops
over an input array.
Then we gave it a function as input
which is used to calculate something
based on each element of the array.
We have created a bunch
of different callback functions for this
and we could create even more.
This is way better than having one big function
calculating all of this stuff at the same time,
because it creates more modular and readable code.
Each function here, of these three that we coded here,
each one has a simple and single task.
So, this is a really good practice.
Okay.
This was an excellent use case
of why and how we should make use
of the fact that we can pass functions around
just like variables.
With this simple technique,
we wrote cleaner code,
and this code is more reusable and readable,
which is really cool.
All right.
See you in the next lecture.