JavaScript Is Everywhere, Even In Spaceships! Level Up Your Skills & Learn 11 Core JavaScript Functions To Remarkably Improve Code Quality.
Paul Knulst in Programming • Jun 21, 2022 • 11 min read
It doesn't care if you working with backend or frontend (or even SPACESHIPS!), JavaScript could be used everywhere because it is a quite flexible language. It has hardcore functional programming patterns as well as classes and its similarity to other "C-like" languages enables an easy transition for every developer.
If you want to level up your skills in JavaScript, I would suggest learning about, practicing, and mastering the following very important core functions that are available in the language. You will not need every function for solving most problems but they can help you to avoid heavy lifting in some cases, while in others, they will reduce the amount of code that you have to write.
1. map()
One of the most important JavaScript functions is map()
! Also, it is one function that gives the most trouble to people who learn JavaScript. This happens because the way this function works is an idea taken from Functional Programming which most developers are not familiar with. It seems strange or even wrong to our biased brains.
The function map()
is very simple. It attaches itself to an array and converts each item into something else, resulting in a new array. This conversion is done by an anonymous function provided in the map brackets.
That's all that map does!
At first, the syntax for map()
might take some time to get used to but after mastering it will be one of your best friends working with JavaScript.
Why You Might Want To Use map()
?
For instance, let's say we recorded the amount of water in a fountain for each day of the last week and stored it in an array. At the end of the week, you are told that the measurement tool was not as accurate as possible and the amount of water was 3.2 liters less than it should be.
With the map()
function you can easily solve this issue by doing this:
const dailyReadings = [34.2, 35.4, 40.1, 35.2, 33.5, 36.5, 38.7];
const correctedDailyReadings = dailyReadings.map(day => day + 3.2);
console.log(correctedDailyReadings); //gives [37.4, 38.6, 43.3, 38.4, 36.7, 39.7, 41.9]
You can find another very practical example in the world of React when you create DOM element lists from arrays. This is a common pattern in React and will be achieved by this piece of code:
export default({articles}) => {
return links.map(article => {
return (
<div className="link" key={article.id}>
<div className="article-name">{article.name}</div>
<div className="article-desc">{article.description}</div>
</div>
);
});
};
Now you can argue that map()
is nothing but another implementation of a for
loop and you will be right but notice that maybe this is your object-oriented trained mind that makes this argument.
2. filter()
filter()
is an unbelievable useful JavaScript function that you can use in many situations because it filters an array based on a given rule/logic. This rule/logic will be provided as anonymous functions.
To show how filter()
is working we can reuse the previous fountain example. Assume that the array contains the amount of water stored within the fountain (This time measurement tool works as expected). Now, we want to find out how often the amount was lower than 36 liters. This can be achieved using the filter()
function:
const dailyReadings = [34.2, 35.4, 40.1, 35.2, 33.5, 36.5, 38.7];
const daysWithLowAmount = dailyReadings.filter(day => {
return day < 36
});
console.log("Days with low amount of water: " + daysWithLowAmount.length); // 4
console.log(daysWithLowAmount); // [34.2, 35.4, 35.2, 33.5]
It is important that the anonymous function that you pass to filter()
has to return a Boolean value: true
or false
. The Boolean expression is used by the filter()
function to determine if a value should be inserted in the newly generated array or not.
Within the anonymous function, you can implement any amount of complex logic to filter the data; you can read user inputs, make any API call, and so on, as long as you return a Boolean value in the end.
BEWARE: Keep in mind that filter()
always returns an array. This is also the case if the filtered data is empty. Often this leads to subtle bugs within code snippets because filter()
is used this way:
const dailyReadings = [34.2, 35.4, 40.1, 35.2, 33.5, 36.5, 38.7];
const daysWithCriticalAmount = dailyReadings.filter(day => {
return day < 30
});
if(daysWithCriticalAmount) {
console.log("The amount of water was critical");
} else {
console.log("The amount of water was normal");
}
Did you notice something? The if
condition in the end checks daysWithCriticalAmount
which is actually an array that is empty because there was no day with less water than 30.
Surprisingly, this mistake is done too often if you are rushing toward a deadline and just want to implement a filter method fast. The problem with this piece of code is that especially JavaScript (Yeah, JavaScript is weird) is an inconsistent language in many ways. Sometimes the "truthiness" of things is one of them.
As you maybe know in JavaScript [] == true
returns false and you may think that the above code is correct.
Unfortunately, within an if
condition, []
evaluates to true! In other words, the else block will never be executed.
Fixing this problem is very easy because you only have to check if the length of the resulting array is greater or equal to 1.
3. reduce()
Compared to all the other functions in this article reduce()
is competing for the first place of "confusing, weird and complex JavaScript functions". Although this function is highly important and results in elegant code in many situations, it is avoided by many JavaScript developers. They prefer to write code without the help of reduce()
.
One reason for this is the complexity of reduce()
. It is very hard to understand the concept and the execution of this function. Furthermore, if you read its description, you have to re-read it several times, and still, you doubt yourself if you read it wrong (Happens to me until I saw it in action).
The reduce()
function is used to reduce (obvious isn't it?) the given array to a single value. This could be a number, a string, a function, an object, or whatever else.
If you want to use the reduce()
function to reduce an array you need to supply the needed logic by providing a function. In general, this function will be called the reducer function that transforms the first argument to reduce()
. Also, it contains a second argument that is a starting value and can be a number, a string, etc. The function itself will look like this:
array.reduce(reducerFunction, startValue)
startValue: The startValue passed to reduce()
function is the starting value (obvious...) for the calculation you want to process with the reducerFunction. For example, if you want to execute an addition you might start with 0 and if you want to do a multiplication you should use a value of 1.
reducerFunction: As mentioned before the reducer function is used to convert the array into a single value. It has two arguments: an accumulator
and a variable to store the current value.
The accumulator
is just a fancy name describing the variable that contains the result of the calculation (it is like using total
to sum up all items in an array). Within the reducer function, the accumulator will be initially set to the starting value and then the calculation will be performed step by step iterating through the array while the result of each step is saved within the accumulator.
The second argument of the reducer function is currentValue
and will contain the value within the array at a given position in a specific step. For example, in step 2 while executing the reducer function the variable currentValue
will contain the second value from the input array.
With all this information we should look at the following example which will add every value from an input array within the reducer function:
const input = [1, 2, 3, 4];
const result = input.reduce((acc, currentValue) => acc + currentValue, 0);
console.log(result); // 10
Within the first line, we define the input array that's holding all the numbers we want to add. The next line will contain the input.reduce()
call, which defines the starting value for acc to be 0 because in an addition we should start with 0 to not influence the result. The reducer functions body (acc, currentValue) => acc + currentValue
does a simple addition of the current value and the value that is stored in the accumulator.
If you would do this addition with a for loop it would look like this:
const input = [1, 2, 3, 4];
let result = 0;
for (let i = 0; i < input.length; i++) {
result += input[i]
}
console.log(total)
As you can see the simple for loop example is much longer and not as elegant as using reduce.
4. some()
Imagine you have an array of objects containing Students and their scores in an exam. Now, you want to know if there are students in your class that have a score that is greater than 90% and it does not care if there is one or multiple students that passed that exam with more than 90%.
If you want to do this in JavaScript you can solve the problem while using a loop and a variable that is set to true after the first person is found that has a score greater 90%:
const students = [{
name: "Stud 1",
score: 78,
}, {
name: "Stud 2",
score: 92
}, {
name: "Stud 3",
score: 90
}]
let over90 = false;
for(let i = 0; i < students.length; i++) {
if(students[i].score > 90) {
over90 = true;
break;
}
}
if(over90) {
console.log("There are students with exceptional score!")
} else {
console.log("Unfortunately, nothing is exceptional")
}
For me, this code looks very "ugly", "verbose", or "horrible"!
It could be optimized by using the map()
function that was described earlier but the solution will still be a little bit clunky.
Luckily, JavaScript has a rather neat function called some()
that is available in the core language, works with arrays, and returns a Boolean value. While providing an anonymous function it will filter the input array to solve the problem elegantly:
const students = [{
name: "Stud 1",
score: 78,
}, {
name: "Stud 2",
score: 92
}, {
name: "Stud 3",
score: 90
}]
if(students.some(student => {
return student.score > 90
})) {
console.log("There are students with exceptional score!")
} else {
console.log("Unfortunately, nothing is exceptional")
}
You can see it gets the same input and will produce the same result but in a more elegant way. Also, the amount of code is reduced and it is much more readable than before.
5. every()
Another function that already exists in the JavaScript core language is every()
. This function will return a Boolean value (like some()
) but will test all items within the input array. To do this you have to provide (again) an anonymous function. As an example, we will test if every student has passed the exam by achieving an exam score of 70 or more:
const students = [{
name: "Stud 1",
score: 78,
}, {
name: "Stud 2",
score: 92
}, {
name: "Stud 3",
score: 90
}]
if(students.every(student => {
return student.score > 70
})) {
console.log("All students passed the exam!")
} else {
console.log("Unfortunately, not all students did well")
}
Like some()
this function creates elegant, readable, and maintainable code that is short.
6. includes()
Often, if I want to check an array of the existence of substrings I will use indexOf()
. Unfortunately, I have to look up the docs to know how their return values are.
Luckily, there is a nice alternative in JavaScript that can be used to achieve this: includes()
. The usage is very easy and it is case-sensitive (I guess you wished for it anyway). See the following code snippet for an example:
const numbers = [6, 5, 13, 26, 48, 1];
console.log(numbers.includes(5)); // true
const name = "Paul Knulst";
console.log(name.includes('paul')); // false, because first letter is in small
console.log(name.includes('Paul')); // true, as expected
However, includes can only compare simple values and no objects:
const user = {a: 6, b: 5, c: 26};
console.log(user.includes('b')); // does not work because objects does not have an "includes" method
7. shift()
If you want to remove the first element of an array shift()
is the method you should use because it is easy to remember and intuitive. Notice that you also can do it with splice
(see it later) but shift()
is easier:
const input = [1, 2, 3, 4];
const first = input.shift();
console.log(input); // gives: Array [2, 3, 4]
console.log(first); // gives: 1
As you can see here shift alters the array it is called on and returns the removed element.
Notice: shift is extremely inefficient and should be avoided if you are working with large arrays. Too many calls of shift()
on large arrays can break your applications!
8. unshift()
In contrast to shift()
which removes one element this function is used to add a new element at the beginning of the array:
const input = [1, 2, 3, 4];
input.unshift(0);
console.log(input); // expected output: Array [0, 1, 2, 3, 4]
Notice: Like shift, unshift is extremely inefficient and should be avoided if you are working with large arrays. Too many calls of unshift()
on large arrays can break your applications!
9. slice()
In JavaScript exist a concept that is called slicing which is a function to create a new string containing a part of an original string by providing a starting index and an end index. Now, with help of the indexOf function you can slice an input string to retrieve the searched substring:
const input = "This is a cool article about mandatory JavaScript functions that every developer shoud know";
const start = input.indexOf("cool");
const end = input.indexOf("that");
const headline = input.slice(start, end);
console.log(headline); // "cool article about mandatory JavaScript functions"
Notice that the start index is included in the resulting array but the end index is not. Also, you can see that the space between "functions" and "that" is also not sliced.
Additionally, slicing can also be used with arrays:
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2)); // ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4)); // Array ["camel", "duck"]
10. splice()
splice()
sounds like slice()
and could be compared with it because both functions create new arrays or strings from the original ones. The main small but very important difference is that splice() removes, changes, or adds elements but modifies the original array. This "destructuring" of the original array can lead to huge problems if you do not fully understand how deep copies and references work in JavaScript!
The following example will show how splice()
can be used:
const months = ['Jan', 'March', 'April', 'June'];
const feb = months.splice(1, 0, 'Feb'); // inserts at index 1
console.log(months); // ["Jan", "Feb", "March", "April", "June"]
console.log(feb); // []
const may = months.splice(4, 1, 'May'); // replaces 1 element at index 4
console.log(months); // ["Jan", "Feb", "March", "April", "May"]
console.log(may); // ["June"]
You can see here that splice()
manipulates the original array. If you remove an item it will also return the removed entry but if you add an entry the return array will be empty.
11. fill()
The last JavaScript function is fill()
and is used to change several items to a single value or even reset the full array to their initial values. If you need this fill()
can help you avoid loops to reset the values of an array. Furthermore, the function can be used to replace some or all entries from the array with a given value.
You can see how it works within the following example:
const input = [1, 2, 3, 4, 5, 6];
console.log(input.fill(0, 2, 4)); // [1, 2, 0, 0, 0, 0]
console.log(input.fill(5, 1)); // [1, 5, 5, 5, 5, 5]
console.log(input.fill(6)); // [6, 6, 6, 6, 6, 6]
Conclusion
This list contains functions that most JavaScript developers encounter and use in their careers. Although it is long, it is by no means complete because there are so many more minor but very useful functions in JavaScript: reverse()
, sort()
, find()
, flat()
, entries()
. I would suggest that you read about these functions because you will at any point use them in your JavaScript project.
Furthermore, whenever you can you should explore the core language or famous utility libraries such as lodash to deepen your JavaScript knowledge. It will result in massive productivity and you will learn to create cleaner, compact, readable, maintainable, and usable code!
This article was originally published on my blog at https://www.paulsblog.dev/introduction-to-11-core-javascript-functions-to-improve-code-quality/
Feel free to connect with me on my blog, Medium, LinkedIn, Twitter, and GitHub.
🙌 Support this content
If you like this content, please consider supporting me. You can share it on social media or buy me a coffee! Any support helps!
Furthermore, you can sign up for my newsletter to show your contribution to my content. See the contribute page for all (free or paid) ways to say thank you!
Thanks! 🥰
Photo by Kyle Glenn / Unsplash
Top comments (17)
Worth pointing out that
startValue
inreduce
is optional. If omitted, it will take the first value from the array and the reducing will proceed from there. Care should be taken with this (passing an empty array will cause a TypeError), but it can result in more efficient code.Thanks for adding this! This is a really important addition.
Als, as you said: It should be taken with care because creating errors is really easy as reduce is complex :-D
Reduce is one of these things where you read it in an article like this one or in a bootcamp and think „yeah that‘s totally straightforward“ but then you see what busted shit people are able to do with it in the wild and suddenly you feel like an ape in a cave 😂
Oh yeah. reduce is really weird :-D.
Normally, it looks so simple but in practice it destroy your sanity.
I didn't know about
every()
. Good to know.I used to use
filter()
and compare the resulting and the origin arrays' lengths, but that's nicer.Instead of
some()
I could also usefind()
. Is there any reason why I shouldn't use it instead?That's a good question.
As I know in terms of performance they are the same.
The main difference is that
find()
will return the first element which satisfies the provided function andsome()
will return true or false.So if you want to find AND return an element you should use
find()
. If you only want to know if the array contains the element you should usesome()
array-methods.github.io
This is really helpful!
thank you
I didn't know about the some() function before
No problem. Hopefully, you will use it now. It sometimes can help. Especially, if you only want to check if a given comparison is true for the array and do not want to return the element where it is true.
Thanks so much for this ;D
Thank you for reading it! Hope it helps :)
Loved the article! All of these array methods are very useful.
Thank you for your feedback :)
There is no requirement that the functions passed to map, filter etc. be anonymous or even arrow/lambdas. Well-named functions improve code quality (except in the most trivial cases).
Filter, some, every etc. expect "truthy" and not Boolean but using truthy instead of true in most cases is a hack which does not improve code quality:
You haven't defined what code quality means and I dare to disagree that these (very basic) array methods make the quality of your code better.
So maybe could you please elaborate on what code quality means and how exactly this type of methods makes the quality of the code higher?
Loved the article! All of these array methods are very useful. You can see more article like this on this website