Whether you're just starting to learn JavaScript, or would like to start learning it better (such as for a coding interview with a company), there are a lot of built-in methods provided that can help to make things easier and keep you from having to spend unnecessary time so you can do better things with your life. Why write any more code than you have to, right? Fortunately, JavaScript has a lot of built-in methods that turn out to be incredibly useful, and you can apply them in a wide variety of situations. With that in mind, let's take a look at some of the most common real-world coding problems you might expect to run into and how you can use JavaScript's built-in methods to solve them.
Working with strings
Problem: user input is almost always stored as a string in web forms
In most HTML-based forms you see online, many of the <input> elements end up storing actual user input as a string, even for inputs that are supposed to represent numbers. Naturally you'd expect <input type="text"> to store its actual input value as a string, but surprisingly, even <input type="number"> will end up having a string value as well. Here’s some very basic HTML (with JavaScript) that demonstrates the problem:
<form>
<label for="num"></label>
<input type="number" id="num">
<span id="submit">Submit</span>
</form>
<script>
function submit() {
var num = document.getElementById("num");
console.log(typeof num.value); // this shows "string", not "number"
}
document.getElementById("submit").addEventListener("click", submit, false);
</script>
Clearly this presents a problem if you might want to do a numeric operation on the user input, like a mathematical operation for example. How can you solve this problem?
Solution: convert user input to numbers
Depending on which type of number you might want (an integer or floating-point), JavaScript offers a few built-in methods for the purpose of converting strings to numbers: parseInt(), parseFloat(), and Number(). All of these are standalone methods and do what you would expect them to do:
console.log(parseInt("16")); // displays 16
console.log(parseFloat("11.25")); // displays 11.25
console.log(Number("16")); // also displays 16
And just to make sure that these are all numbers instead of strings, you can do this to verify that (if you're not familiar with "typeof", it can be used to get the type of any variable):
console.log(typeof parseInt("16")); // these will all correctly show "number"
console.log(typeof parseFloat("11.25"));
console.log(typeof Number("16"));
However, where things start to get finicky is when you have non-numeric characters in your string. What would you expect the below statements to do? Go ahead and try them in an online editor like JSBin, JSFiddle, REPL.it, or a local Node.js environment:
console.log(parseInt("16K"));
console.log(parseFloat("105.25percent"));
console.log(Number("10units"));
You’ll see that you can still get 16 from a "16K" string input, and 105.25 from "105.25percent", but Number() doesn't do the same. As the method names imply, the two "parse" methods can get the number from your string input even if it includes extra non-numeric characters, but Number() will take only a numeric input and convert it to a number.
Before moving on, one last trick you can use with the "parse" methods is to add a second parameter called the "radix", or what's commonly called a base. If you're familiar with base 2 (binary) or base 16 (hexadecimal) numbers, you can convert them! You can see that with these two statements:
console.log(parseInt("0F", 16)); // hexadecimal to decimal
console.log(parseInt("110", 2)); // binary to decimal
Problem: user input will inevitably contain mistakes
In the real-world, user input won't always be perfect, because people make mistakes. They might insert extra characters they didn't mean to type, they might use the wrong case (uppercase or lowercase), or they'll add unintentional white space at the beginning or end. While removing extra characters is next to impossible (since you can't know what mistake the user might've made), we can actually take care of the case and white space issues.
Solution: correct user input errors
In real-world scenarios, you'll almost always convert whatever case the user entered and just do a direct convert to lowercase (with some exceptions of course). The primary reason for this is because when you don't know what case the user might have entered, it's almost always considered a coding "best practice" to just make every user input the same case, especially if you're going to store the user input in a database. Or, in other scenarios, you might want to covert something to uppercase instead, like common acronyms (such as "HTML", "CSS"). You can do this by using either of two very straightforward methods toLowerCase() and toUpperCase() - by simply chaining the method to the end of a string or string variable. Here's a hypothetical example using someone's full name:
let full_name_1 = 'William Shatner';
console.log(full_name_1.toLowerCase());
console.log(full_name_1.toUpperCase());
That brings us to another common user input mistake, which is adding extra spaces - at the beginning, at the end, or at the beginning and end. Take these types of problem scenarios which can be common in user inputs:
let full_name_2 = ' leonard nimoy'; // any number of spaces at the beginning...
let full_name_3 = 'james doohan '; // ...or at the end
So you can solve either of these problems with separate methods trimStart() and trimEnd() by chaining them to the end of a string or string variable:
console.log(full_name_2.trimStart());
console.log(full_name_3.trimEnd());
Or you can actually just use the trim() method to conveniently handle both the beginning and end of the string at the same time (note that you might not want to always do this though):
console.log(full_name_2.trim());
console.log(full_name_3.trim());
If you're following along with the train of logic I’ve established so far, at this point you might be wondering "Great so I can eliminate extra spaces at the beginning and end of a string! How about in the middle of the string?" Well, even if you weren't thinking that, it's a reasonable follow-up question, and one we'll cover in the next problem.
Problem: data is either in separate fields, or hasn't been separated out
In real-world applications, you'll very often work with text-based strings that are either directly from user input, or alternately from a database. For example, if you have a form that's collecting user input, you might expect to see input fields for name, address (including postal code), and payment info. Ultimately this user-inputted data might also be stored in a database, so you might see it being retrieved from the database for display in a different part of the app (like on an “Edit Profile” page). As you might expect, sometimes this data is either all stored separately in their own variables (as it should be, for easy maintenance), or you might see multiple fields stored together in one variable (people's full names sometimes fall victim to this trend, but this also typically happens with what's called "UTC datetime format" for dates and times). Fortunately, working with either scenario is made much easier with a variety of built-in string methods.
Solution How to: break apart strings
Method 1 using split()
let full_name_4 = 'Chris Pine';
let person1_first_name = 'Chris';
let person1_last_name = 'Hemsworth';
Although this isn't exactly the best actual use case of removing spaces from a string (since you usually won't do that with people's names), for our demo purposes we'll stick with this example. Let's say you want to separate someone's first and last names to display only their first name, perhaps for a personal profile page. Doing that is very simple by using the split() method, which does exactly what it indicates, and takes as an argument what's called the "delimiter" - one character that separates words in the string. In our example here, that character is a "space" but in other instances it might be a comma, period, or semicolon. Let’s go ahead and try using split() on the first string variable:
console.log(full_name_4.split(' '));
As you'll see, this actually returns an array, where each element is each "word" in the string. Since we wanted just the first name, we can get that simply by using array notation and grabbing the first element (which is a little more code, so it’s not always the ideal solution):
let full_name_4_array = full_name_4.split(' ');
console.log(full_name_4_array[0]);
Method 2 using substring() and substr()
The substring() and substr() methods also provide string "separation" but have a slightly different use case where you just want to grab a specific part of a string that follows an expected pattern. For example, let's say we have a string like this:
let phone_number = '555-123-4567'; // 10-digit phone numbers in the US
While you could still use split() to grab just the area code if you wanted to, substring() and substr() can also do this, but these methods are used differently, as shown. Both methods take a string-based index to start from, and a second parameter - a string-based index to end at for substring(), or a length for substr().
console.log(phone_number.substring(0, 3)); // 2nd param is an ending index
console.log(phone_number.substr(0, 3)); // 2nd param is length
There are some other subtle differences between how these methods work that are worth looking up, just so that you’re aware of how the differences can impact the string that’s returned.
Method 3 using slice()
And just to add more options, JavaScript also gives you the slice() method, which you can chain to the end of a string or string variable. You can use slice() in a variety of ways by specifying the index to start at, followed by an optional index to end at:
console.log(phone_number.slice(0, 3); // the area code
console.log(phone_number.slice(4, 10)); // the rest of the phone number
So as you might imagine, there are quite a few ways to separate out your strings, no matter what form they might be in.
Solution: combine strings
Fortunately, string combination in JavaScript is extremely simple and you'll almost always use the addition operator (+) to combine multiple strings:
let spock_first_name = 'Zachary';
let spock_last_name = 'Quinto';
let spock = spock_first_name + ' ' + spock_last_name;
But there are two other scenarios to be aware of when you want to form a string combination. If you have an array of strings and want to combine all of the elements together into one “mega” string, you can use the Array's join() method, which takes an optional argument as the delimiter between words:
let scotty_array = ['Simon', 'Pegg'];
console.log(scotty_array.join(' '));
Or you can use the String's concat() method, which can tack multiple strings to the end of a given string.
let actor = 'Chris Pine';
let character = 'Captain Kirk';
let movie = 'Star Trek 2009';
console.log(actor.concat(' / ', character, ' / ', movie));
Problem: finding an item a user is searching for (basic text searches)
One of the most common user inputs you see on the Web are text search inputs, where you can type in some text to search for, and the website or web app will tell you if it found a matching result - for example, the search input on Amazon.com, YouTube.com, and Google.com are all basic text searches. Have you ever wondered how these are actually pulled off behind the scenes? Well, JavaScript makes this super easy for you to do!
Solution: search strings
Let's say you want to find all movies that are Batman-related on Amazon. So we'd probably have at least a few of these titles already stored in an array somewhere (this will usually be an array of objects in the real-world, but we’ll simplify down to an array of strings for demo purposes):
let movies = [
'The Batman [2022]',
'Batman v Superman: Dawn of Justice',
'The LEGO Batman Movie',
'Man of Steel',
'Batman Begins',
'Batman [1989]'
];
We're also going to skip a looping structure for this array since that'll be the focus on a problem below, so we'll just get to solving the underlying problem first. How do you actually find which title(s) match a user input for "Batman"? JavaScript makes this incredibly easy with the includes() and indexOf() methods (which both do basically the same thing, but have different advantages) and are aptly named - includes() will tell you if one string "includes" another, and indexOf() will do the same thing but also give you the index of where the string was matched. You can use includes() by chaining it to the end of a string or string variable, and inserting the string that you’re looking for as its argument:
let user_search_string = 'Batman';
console.log(movies[0].includes(user_search_string)); // returns a Boolean true
While we're solving this problem, why don't we add some code that we've already learned to make the user search even more flexible? For example, what if the user didn't capitalize "Batman"? We can cover that scenario by augmenting the previous code with toLowerCase():
let user_search_string = 'batman'; // note the different input
console.log(movies[0].toLowerCase().includes(user_search_string));
Or you can use indexOf(), which will return either the index at the point where it matched, or an integer -1 value if it didn't find the string, which you can then use as a condition/flag value.
let user_search_string = 'batman';
console.log(movies[2].toLowerCase().indexOf(user_search_string)); // searching 'The Lego Batman Movie'
console.log(movies[3].toLowerCase().indexOf(user_search_string)); // searching 'Man of Steel'
// Using -1 from indexOf() as a condition/flag value
if (movies[3].toLowerCase().indexOf(user_search_string) === -1) {
alert("No results found...");
}
Problem: time and/or date is not in a display-ready format
As you get deeper into web development, you'll eventually come across scenarios where times and dates will look more cryptic than anything. For example, what I mentioned before with "UTC datetime format". Haven't heard of that before and totally unfamiliar with what it is? Well here's a crash course in what it is, and how you can solve the problem of converting it to something much more user-friendly.
Solution: convert times and dates
"UTC datetime format" refers to a formatted date & time string that conveniently stores date together with a time, in a form that's generally easy to sock straight into your database, and that's also actually not too hard to manipulate into different forms either. This is what it looks like: "2022-08-12T23:40:12Z". You can make out the date, and the time (it's in 24-hour format), but what are the "T" and the "Z"? "T" is mostly just a delimiter for the time to indicate where that starts, while "Z" indicates it's in 24-hour format (you won't see “Z” for a time that's in 12-hour time format).
All this is just to say that dates & times will be in "UTC datetime format" in certain parts of your app, and it'll be up to you to convert these to something much more palatable to a user, like "August 12 2022 @ 11:40 PM". You can actually implement almost any date & time format you can think of - showing just the date, or just the time, or any variation thereof. So let's assume you're starting with a date/time like this:
let date_right_now = "2022-08-12T23:40:12Z";
Getting a form that's easier to read is surprisingly easy with some very simple methods. First you have to use JavaScript’s built-in Date() method to create a “Date” type variable, which has several different methods available on it that all return something slightly different:
let date = new Date(date_right_now);
console.log(date.toDateString());
console.log(date.toLocaleDateString());
console.log(date.toLocaleString());
console.log(date.toString('YYYY-MM-dd'));
If you need to do some manual customization on the format though, you can add some options to toLocaleDateString() like this, for a very user-friendly format:
let date_formatted_nicely = new Date(date_right_now)
.toLocaleDateString('en-us',
{ weekday: "long", year: "numeric", month: "short", day: "numeric"}
);
console.log(date_formatted_nicely);
Needless to say there are tons of options you can play with that are available on JavaScript's "Date" object, for any type of manual customization you might want to do - you can extract the month, day, and year (or any combo of them), along with hours, minutes, and seconds (and any combo of those) to display date and time in absolutely any format you might want to display.
Working with arrays
Problem: finding relevant items that a user is searching for (complex search forms)
A very common situation you probably run across all the time as a user on websites and web apps are more complex search forms - i.e., search inputs augmented with selectable filters. You'll see these a lot on e-commerce sites like Amazon, eBay, and almost any kind of website you buy things from - including flight and hotel reservations - to "drill down" further on your search results. Most of the time, search inputs will return all of the results found, but it's often more useful to see just the most relevant results, especially when there might be a lot. Have you ever wondered how these are actually done behind the scenes?
Solution: search arrays of objects, and search for values in object properties
Let's go back and look at a line of code that was previously written, but this time we're going to turn it into an array of objects, rather than a simple array of strings:
let movies = [
{ title: 'The Batman [2022]', year: 2022 },
{ title: 'Batman v Superman: Dawn of Justice', year: 2022 },
{ title: 'The LEGO Batman Movie', year: 2017 },
{ title: 'Man of Steel', year: 2005 },
{ title: 'Batman Begins', year: 2005 },
{ title: 'Batman [1989]', year: 1989 }
];
Now let's say you want to show to a user only the movies that have "Batman" in the title. In order to do this, you have to "iterate" over the array of objects, and "filter" out the elements that have a matching title. While we could use a traditional for-loop, JavaScript gives you a filter() method that's built for this exact purpose. You can use it by chaining it to an array, and its primary argument is an “arrow function” that contains whatever logic you want to use for filtering elements:
movies.filter(element => {
console.log(element); // this is where to add a condition to "filter"
});
In its current state as shown above, filter() won't do anything other than show each element, because we haven't added an actual filter yet. But it's easy enough to do, as we've already done before. Since the filter() method is functional and returns a new array rather than changing the original array, you actually have to set up a new variable to capture the result first:
let filtered_movies = movies.filter(movie => movie != null); // not filtered yet
Now we can finally add the filter condition for a user search, using what we've previously learned about string conversion from toLowerCase() and includes():
let user_search_string = 'batman';
let filtered_movies = movies.filter(movie =>
movie.title.toLowerCase().includes(user_search_string)
);
console.log(filtered_movies);
Now what if we want only movies released since 2000? It's surprisingly easy if we just tack on another filter()!
let filtered_movies_since_2000 = movies
.filter(movie => movie.title.toLowerCase().includes(user_search_string))
.filter(movie => movie.year > 2000);
console.log(filtered_movies_since_2000);
As you'd expect, you can chain any number of additional filter() calls to further refine your results, or you can use any of the other string-searching methods.
Problem: maintaining user-generated lists of data
Lastly, another very common "feature" you expect to have nowadays in most modern web apps is the ability to create your own list of items and modify them as you wish - for example: wishlists on Amazon, watchlists on Netflix / Hulu / <insert streaming platform of choice>, Watch Later on YouTube. Have you wondered how these are also done behind the scenes? It's actually much simpler than you might think!
Solution: add and remove elements from arrays, and reorder arrays
We're going to reuse our movies[] array from before and just think of it as a wishlist for this problem. Let's say we want to add another movie to our list. We can do that using the array push() method, which takes an element to add to the array (we need to add a full “movie” object for our movies[] array):
movies.push({ title: 'The Dark Knight', year: 2007 });
movies.push({ title: 'Batman Forever', year: 1995 });
If we made a mistake and want to remove the last thing we added, we can use pop():
movies.pop();
You know how Amazon wishlists have a "Move to top" feature, and wondering how you can do the same? That's easy with JavaScript's unshift() method, which takes an element and inserts it at the beginning of an array. However, in our example movie wishlist, we should get the last item in the movies[] array first, and then we can move it to the top:
let last_movie = movies[movies.length - 1];
movies.unshift(last_movie);
console.log(movies);
We can also remove the first element from the array using shift() - you can think of "shift" as moving everything up (or left), and "unshift" as moving everything down (or right):
movies.shift();
console.log(movies);
Now let's imagine your UI allowed you to select multiple movies to remove at the same time. You can effectively remove multiple elements from an array using JavaScript's slice() method, which takes a start and optional end index, like this:
let modified_list = movies.slice(4, movies[length-1]); // a new array minus 4 movies from the list
console.log(modified_list);
Or alternately, you can modify arrays directly with the splice() method, which takes a start index, optional number of elements to delete, and elements to add in place:
movies.splice(1, 2,
{ title: 'The Dark Knight Rises', year: 2012 },
{ title: 'Zack Snyder Justice League', year: 2021 }
);
console.log(movies);
If you followed along with all of this code from the top, you’ll now see that you have a list of only the top-quality Batman movies!
The Verdict
Now that you’ve seen some common types of general problems you might expect to see in a real-world app, along with how to solve them, you should have a better understanding of JavaScript’s built-in string and array methods and how to take advantage of them. Now try to see if you can apply them in unconventional ways to find solutions for future problems more easily and quickly!