30 Days Of JavaScript.9
Day 9. Higher Order Functions
On
Day 9
, I learned about higher order function, which takes another function as a parameter. Also I learned lots of built-in methods to manipulate an array easier. Take time reading the documents!
Higher Order Function
Higher order functions are functions that take other function as a parameter, or return a function as a value. The function passed as a parameter is called a callback.
1. Callback
A callback is a function which can be passed as parameter to other function.
const callback = (n) => {
return n ** 2;
}
function cube(callback, n) {
return callback(n) * n;
}
console.log(cube(callback, 3)); // 27
2. Returning function
Higher order functions return function as a value.
const higherOrder = n => {
const doSomething = m => {
const doWhatEver = t => {
return 2 * n + 3 * m + t;
}
return doWhatEver;
}
return doSomething;
}
console.log(higherOrder(2)(3)(10)); // 23
Example of using callback function.
const numbers = [1, 2, 3, 4];
const sumArray = arr => {
let sum = 0;
const callback = function(element) {
sum += element;
}
arr.forEach(callback)
return sum;
}
console.log(sumArray(numbers)); // 10
The upper code can be simplified as below, by just passing the callback function to the parameter.
const numbers = [1, 2, 3, 4];
const sumArray = arr => {
let sum = 0;
arr.forEach(function(element) {
sum += element
})
return sum;
}
console.log(sumArray(numbers)); // 10
3. Setting Time
In JavaScript, I can execute some activities in a certain interval of time(setInterval
). Also, I can delay the execution of activities by setting the waiting time(setTimeout
).
1) Setting Interval using a setInterval
function
function callback() {
//code goes here
}
setInterval(callback, duration);
In JavaScript, setInterval
higher order function is used to do some activity continuously with in some interval of time. The setInterval
global method takes a callback function and a duration as a parameter. The duration is in milliseconds, and the callback will be always called in that interval of time.
function sayHello() {
console.log('Hello');
}
setInterval(sayHello, 1000);
// it prints hello in every second(1000ms = 1s)
2) Setting a time using a setTimeout
function callback() {
//code goes here
}
setTimeout(callback, duration);
In JavaScript, setTimeout
higher order function is used to execute some action at some time in the future. The setTimeout
global method takes a callback function and a duration as a parameter. The duration is in milliseconds, and the callback wait for that amount of time.
function sayHello() {
console.log('Hello');
}
setTimeout(sayHello, 2000);
// it prints hello after 2 seconds
4. Functional Programming
Instead of writing regular loop, JavaScript introduced lots of built-in methods which can help solving complicated problems. All built-in methods take callback function.
- forEach, map, filter, reduce, find, every, some, and sort
1) forEach()
The forEach()
method iterates the array elements, and executes a provided function once for each array element. It is only used with arrays. It takes a callback function with elements, index parameter and array itself. The index and array parameter are optional.
//using function declaraion
arr.forEach(function(element, index, arr) {
console.log(index, element, arr)
})
//using arrow function
arr.forEach((element, index, arr) => {
console.log(index, element, arr)
})
//using arrow function and explicit return
arr.forEach((element, index, arr) =>
console.log(index, element, arr)
)
I didn’t know what ‘explicit return’ would mean, so I searched and found this article. The arrow function can have either ‘explicit return’ or ‘implicit return’. The ‘explicit return’ is when I use return
keyword, while ‘implicit return’ is when I skip the return
keyword.
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => console.log(num + 10));
// 11 12 13 14 15
let sum = 0;
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => sum += num);
console.log(sum); // 15
2) map()
map()
iterates and modifies the array elements. It takes a callback function with elements, index, array parameter and returns a new array.
const modifiedArray = arr.map(function(element, index, arr) {
return element;
})
//using arrow function and implicit return
const numbers = [1, 2, 3, 4, 5];
const numbersSquare = numbers.map((num) => num * num)
console.log(numbersSquare); // (5) [1, 4, 9, 16, 25]
const countries = [
'Albania',
'Bolivia',
'Canada',
'Denmark',
'Ethiopia',
'Finland',
'Germany',
'Hungary',
'Ireland',
'Japan',
'Kenya',
]
const countriesFirstThreeLetters = countries.map((country) =>
country.toUpperCase().slice(0, 3)
)
console.log(countriesFirstThreeLetters);
// (11) ['ALB', 'BOL', 'CAN', 'DEN', 'ETH', 'FIN', 'GER', 'HUN', 'IRE', 'JAP', 'KEN']
3) filter()
filter()
filters out items which fulfill filtering conditions and return a new array of those items. Inside the callback function, I should put a predicate to test each element of the array.
const countriesContainingLand = countries.filter((country) =>
country.includes('land')
)
console.log(countriesContainingLand);
// (2) ['Finland', 'Ireland']
const scores = [
{ name: 'Asabeneh', score: 95 },
{ name: 'Lidiya', score: 98 },
{ name: 'Mathias', score: 80 },
{ name: 'Elias', score: 50 },
{ name: 'Martha', score: 85 },
{ name: 'John', score: 100 },
]
const scoresGreaterThan90 = scores.filter((score) => score.score > 90)
console.log(scoresGreaterThan90);
// [{name: 'Asabeneh', score: 95}, { name: 'Lidiya', score: 98 }, {name: 'John', score: 100}]
4) reduce()
reduce()
takes a callback function. The callback function takes accumulator, current, and initial value(optional) as a parameter. An accumulator is a variable to store the sum of the element. The reducer walks through the array element-by-element and pass the return value from the calculation on the preceding element. It returns a single value-the final result of running the reducer across all elements of the array.
It is a good practice to define an initial value for the accumulator value. If I don’t specify the initialValue
parameter, by default the accumulator will get the first value(index 0) of the array. If the array is empty, there will be an error.
arr.reduce((acc, cur) => {
//some operations goes here before returning a value
return
}, initialValue)
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 15
5) every()
every()
checks if all the element of the given array pass the test implemented by the provided function. It returns a Boolean value.
const names = ['Louis', 'Paul', 'Brian', 'Max'];
const areAllStr = names.every((name) =>
typeof name === 'string');
console.log(areAllStr); // true
6) find()
find()
returns the first element value which satisfies the condition. If there’s no values that satisfy the testing function, undefined
is returned.
const ages = [24, 22, 33, 25, 36, 21];
const ageOver30 = ages.find((age) => age > 30);
console.log(ageOver30); // 33
7) findIndex()
findIndex()
returns the index(position) of the first element which satisfies the condition.
const names = ['Cindy', 'Cecilia', 'Alice', 'Stella', 'Olivia']
const longName = names.findIndex((name) => name.length > 6);
console.log(longName); // 1
8) some()
some()
tests whether at least one element in the array passes the test implemented by the provided function. It returns a Boolean value.
const bools = [true, true, true, false];
const areSomeFalse = bools.some((b) => b === false);
console.log(areSomeFalse); // true
9) sort()
The sort()
method arranges the array elements either ascending or descending order. By default, the sort()
method sorts values as strings. For string items it works fine but for number items, it returns a wrong result. sort()
modifies the original array, so it’s recommended to copy the original data before using sort()
.
- Sorting String Values
const products = ['Coffee', 'Tea', 'Icecream', 'Pie', 'Soda'];
console.log(products.sort());
//(5) ['Coffee', 'Icecream', 'Pie', 'Soda', 'Tea']
console.log(products);
//(5) ['Coffee', 'Icecream', 'Pie', 'Soda', 'Tea']
//Now the original array is also sorted
- Sorting Numeric Values
sort()
converts the itmes to string, so there can be a case that ‘100’ comes before ‘11’ when sorted in ascending order, like below.
const numbers = [10, 11, 100, 1000, 1500];
console.log(numbers.sort());
// (5) [10, 100, 1000, 11, 1500]
To avoid it, we use a compare callback function inside the sort method, which returns a negative, zero or positive value.
const numbers = [9, 3.5, 100, 37];
//function expression, ascending order
numbers.sort(function (a, b) {
return a - b;
})
console.log(numbers);
// (4) [3.5, 9, 37, 100]
//arrow function expression, descending order
numbers.sort((a, b) => b - a);
console.log(numbers);
// (4) [100, 37, 9, 3.5]
I had a little difficulty understanding how it works, so I looked up the document. The compareFunction
works like below.
- If the result is negative a is sorted before b.
- If the result is positive b is sorted before a.
- If the result is 0 no changes are done with the sort order of the two values.
Here’s the form that the compare function would have(in ascending order):
function compare(a, b) {
if (a is less than b by some ordering criterion) {
return -1;
}
if (a is greater than b by the ordering criterion) {
return 1;
}
// a must be equal to b
return 0;
}
- Sorting Object Arrays
Whenever we sort objects in an array, object key is used to compare.
objArr.sort(function (a, b) {
if (a.key < b.key) return -1;
if (a.key > b.key) return 1;
return 0;
})
objArr.sort(function (a, b) {
if (a['key'] < b['key']) return -1
if (a['key'] > b['key']) return -1
return 0;
})
const umbrellaAcademy = [
{ name: 'Luther', age: 31 },
{ name: 'Diego', age: 29 },
{ name: 'Allison', age: 31 },
{ name: 'Klaus', age: 34 },
{ name: 'Five', age: 58 },
{ name: 'Ben', age: 16 },
{ name: 'Vanya', age: 29 }
]
umbrellaAcademy.sort(function (a, b) {
if (a.age < b.age) return -1;
if (a.age > b.age) return 1;
return 0;
})
console.log(umbrellaAcademy);
Leave a comment