Just like numbers, strings, booleans, arrays, and objects
Anywhere you can assign or otherwise use a value, you can assign or use a function as the value.
This is the case we’re used to.
const add = (a, b) => a + b;
The const add
just declares a variable.
The =
assigns it a value.
And the value is the function (a, b) => a + b
.
const anotherName = add
This is evaluated by first evaluating the variable add
which gives us the function value.
Note it does not call the function; it just gets the value.
That value is then assigned to the variable anotherName
.
We can also use functions without giving them a name.
One scenario we’ve seen recently for assigning a function to the property of an object is to register an event handler.
const b = document.querySelector('button');
b.onclick = (e) => {
console.log('Button was clicked');
};
This works because when a button in a web page is clicked, the browser will find the value of the button object’s onclick
property and call it.
We can also define a named function
const clicked = (e) => {
console.log('Button was clicked');
};
And then use it as an event handler
const b = document.querySelector('button');
b.onclick = clicked;
Once again, note no ()
s after clicked
as we are not calling it, we are just getting its value.
So far this year we’ve worked with functions that take numbers, booleans, strings, arrays, and objects as arguments and return them as values.
Can we pass a function as an argument to another function? Can we return a function as a value?
Functions that take functions as arguments or return functions as a values, are called “higher-order functions” or “HOFs”.
In Javascript, arrays have a number of methods that are higher-order functions.
One simple one is every
which takes a function and returns true if the function returns true for every element in the array.
Suppose we have this function, which given a number from 0.0 to 1.0 says whether it should be considered “heads” (as in a coin flip).
const heads = (n) => n > 0.5;
(Incidentally, functions that return a boolean value are sometimes called “predicates”.)
Now lets make an array tosses
that contains a bunch of random numbers from 0.0 to 1.0.
const tosses = [];
for (let i = 0; i < 10; i++) {
tosses.push(Math.random());
}
let allHeads = true;
for (let i = 0; i < tosses.length; i++) {
if (!heads(tosses[i])) {
allHeads = false;
}
}
// allHeads is either true or false
every
const allHeads = tosses.every(heads); // either true or false
const allHeads = tosses.every(n => n > 0.5);
filter
Takes a one-argument predicate, i.e. a function that takes one argument and returns true
or false
.
Returns an array containing only those elements of the original array for which the predicate returns true.
const ns = [1, 2, 3, 4]
ns.filter((n) => n % 2 === 0) ⟹ [2, 4]
map
Takes a one-argument function.
Returns an array of same size as the original but with new values produced by calling the function on each of the original elements.
const ns = [1, 2, 3, 4]
ns.map((n) => n ** 2) ⟹ [1, 4, 9, 16]
reduce
Takes a two-argument function and an initial value.
Returns a value produced by repeatedly calling the function with to either the initial value or the previous value returned by the function and the next element of the array.
const ns = [1, 2, 3, 4]
ns.reduce((tot, n) => tot + n, 0) ⟹ 10
flatMap
Takes a one-argument function that returns an array.
Returns an array with the elements of all the arrays returned by calling the function on each of the elements of the original array flattened into a single array.
const ns = [1,2,3,4]
ns.flatMap((x) => [x, x]) ⟹ [1, 1, 2, 2, 3, 3, 4, 4]
every
Takes a predicate function.
Returns a boolean which is true, if and only if the predicate returns true for every element of the array.
const ns = [1,2,3,4]
ns.every((n) => n % 2 === 0) ⟹ false
some
Takes a predicate function.
Returns a boolean which is true, if and only if the predicate returns true for some element of the array.
const ns = [1,2,3,4]
ns.some((n) => n % 2 === 0) ⟹ true
Start with some definitions:
const ns = [1,2,3,4]
const isEven = (n) => n % 2 === 0
const square = (n) => n ** 2;
const add = (a, b) => a + b;
Then:
ns.filter(isEven) ⟹ [2, 4]
ns.filter(isEven).map(square) ⟹ [4, 16]
ns.filter(isEven).map(square).reduce(add, 0) ⟹ 20