JavaScript is the language of the web. If you want to code for the web, you need to know JavaScript inside and out. This course will help you learn JavaScript from start to finish.

This course is 7 hours 30 minutes long, and it’s split into 78 lessons in total. You’ll find it’s a great resource that you will come back to often so make sure you bookmark the parts that interest you. 

I encourage you to follow along with this course, and you’ll learn about all the most important features of JavaScript.

Welcome to Modern JavaScript Fundamentals. In this introductory lesson, we’ll take a look at the scope of the course. 

Here is what we’ll cover:

Let’s get our development area set up and ready for coding! In this lesson I’ll show you how.

To set up JavaScript and our working environment, we’ll use the following tools: 

In this lesson, we’ll look at one of the most fundamental units of a JavaScript program—the humble variable. We’ll see the different ways that a variable can be declared and then assigned a value, and some other general bits of information about variables that you should probably be aware of.

In this lesson, we’ll take a look at the different data types that can be used in JavaScript and what each type can be used for. We’ll cover primitives, composites, and special data types.

Special characters like + and - can be used in different combinations to perform operations on different things. Let’s see how some of the more basic operators like arithmetic, assignment, and comparison operators behave.

In this lesson we’ll continue looking at JavaScript’s many operators. This time, we’ll focus on unary operators, logical operators, the comma operator, and the spread operator.

In this lesson we’ll look at exponentiation operators and logical assignment operators. 

Not all operators are created equal! In this lesson, we’ll see the order in which operators are evaluated when more than one type of operator is used in an expression.

Some words in JavaScript are special and can’t be used as identifiers. Let’s just take a moment to review these to make sure we don’t cause unexpected errors in our programs.

Numeric separators make working with large constants a little easier.

Long numbers can be hard to read. Here, the numeric separators make it easy to see the number is one billion.

Strict mode is a useful execution mode for JavaScript that can prevent many errors and should always be used. In this lesson we’ll learn all about it.

For example, the following function, in strict mode, will throw a compile-time exception about assigning to NaN. The idea is to catch a mistake when you compile the code, instead of waiting for the program to fail when you run it.

In this section, we’ll learn about the nullish coalescing operator: ??. Nullish coalescing makes it easy to retrieve the value of an expression, or some default value if that expression is null.

Here are a couple of examples of nullish coalescing in operation:

Functions are the cornerstone of JavaScript. In this lesson we’ll look at some basic features of functions.

Here is a very basic example of a function that just logs a message to the console:

Arrays are one of the most commonly used structures for storing data, and you will use them all the time. In this lesson we’ll focus on the basics: what arrays are and how they can be created, accessed, and modified.

Here’s a simple example of an array of types of fruit. Note that an array can have duplicates.

Objects are a fundamental concept in JavaScript, and ultimately, most entities are objects in one way or another. In this lesson, we’ll focus on how objects can be created and the different ways that their properties can be accessed.

Sets are JavaScript objects that store unique values of any type. Set is one of the collection classes recently added to JavaScript.

Unlike arrays, sets cannot have duplicates:

Maps are objects that store key-value pairs. In the case of maps, both the keys and values can be of any type.

Following on from the previous lesson, let’s take a look at WeakSets and WeakMaps. A WeakSet contains weakly referenced unique objects, whereas a WeakMap has weakly referenced objects as keys.

What happens when we need to do one thing if a condition is true, or something else if it isn’t? We use an if statement, that’s what, and in this lesson we’ll learn all about if statements and the ternary operator.

Here’s an example of using a ternary operator:

When code throws errors, how do you catch them? In this lesson, we’ll see how. 

Similar to an if statement is the switch statement, which allows us to take a different code path based on the value of something. I’ll show you how it works in this lesson.

The most basic way of iterating a data structure is the for loop. Let’s take a look at how it works.

This example builds a string with nine * characters. Of course, it would be easy to hard-code this, but what if it was 90 characters? Or 9,000?

While a classic for loop is used for iterating arrays, a for .. in loop is used to iterate objects.

The for .. of loop is a new construct that allows us to iterate over the values in a collection instead of the keys. Let’s take a look at how we can use it to iterate arrays, maps, or other iterable objects.

Let’s learn about the iteration protocol and see how to iterate some of the data structures that we looked at earlier.

JavaScript also supports two additional types of loops: while and do .. while loops. These loops differ from for loops in that they test a condition evaluating to true or false at each iteration step, rather than iterating a range of numbers or elements in an object. We’ll cover the syntax of both while loop types and look at some considerations of their usage.

Strings have lots of different properties and methods we can use in order to transform them or glean useful information from them. Let’s see some of the more common things we can do with strings.

Often, when you are using strings, you’ll want to do some formatting, like padding the beginning or end, trimming whitespace, or replacing characters. In this lesson you’ll see how.

Some examples of padding and trimming functions:

JavaScript now features native templating in the form of template literals, which are a special type of string that can contain expressions. We can also use a slightly more advanced template called a tagged template. Let’s look at both of these features in this lesson.

Template literals are great for building strings for output.

In this lesson, we’ll take a look at some of the properties and methods that make up the API of the built-in Number object.

Sometimes a plain Number is not big enough to store the result of a calculation. For example, exponentiation can overflow the numeric data type quickly.

Here’s an example that shows how powerful and easy to use the BigInt type is.

Arrays also have a variety of different properties and methods. Let’s review the most commonly used.

Arrays have so many useful methods that I had to break the array lesson into two parts! In this lesson, we continue looking at how we can work with arrays, this time focusing on methods for iterating and transforming them.

If you want to find out if an array contains a certain element, then you’ll want to search with a method like includes().

If you have an array of arrays, you can combine all the elements into a single array with flat().

Object is a special type of object which also has its own properties and methods. In this lesson, we learn about instances of Object and how they can be used.

Recent versions of JavaScript have introduced some new tools that we can use when creating object literals, including shortcuts for defining properties and methods, dynamic keys, and the new assign method.

All object instances inherit properties and methods from the prototype of their constructor. We can find out whether a property is defined on an object directly or inherited from the prototype. To do this, we use the hasOwnProperty method of the Object constructor. We’ll cover this and some other Object constructor methods in this lesson.

Often we need to access the keys and values of an object as a collection. The Object class provides a number of methods for this, for example keys() and values().

As well as regular object properties, we can also create properties that have getters and setters, which are special functions that run when the property is set or accessed.

We’ve seen how to create objects that have properties and methods, but in this lesson we’ll go a little deeper and see how to create custom objects. We’ll also look at how to specify whether properties are enumerable or configurable.

In this lesson we’ll take a look at the built-in Math object, which provides properties and methods to perform operations on numbers.

In this lesson, we’ll look at how to work with dates and times in JavaScript. I’ll show you how to create new instances of the Date class, modify them, and output them to strings.

Like the Object class, the Array constructor has a couple of useful methods that we can use. In this lesson, we’ll take a look at these methods in detail.

The this object is often confusing to JavaScript beginners. Depending on the context in which it’s used, this can be bound to different objects. In this lesson, we’ll look at some of the ins and outs.

Functions are also objects, and as such they have their own properties and methods that we can use. Let’s take a look at some of the more common function methods.

Scope is an important and sometimes elusive concept in JavaScript. We need to understand scope, so in this lesson we’ll dig in and focus entirely on what it is.

In JavaScript, the global object has a different name depending on the execution environment. For JavaScript in the browser it’s window, on Node.js it’s global, and in a WebWorker it’s called self. That’s where globalThis comes in—to give consistent access to the global object no matter the platform.

Arrow functions give us a much more concise syntax for anonymous functions. They come with a few gotchas, though. For one, this works a little differently in an arrow function. Let’s take a closer look at how to use arrow functions and how this works with them in this lesson.

Arrow functions are great for writing short, succinct functions that transform their input.

Generators are a special type of function that can be paused during execution using a yield expression. Let’s learn how to pass values in to generators, and see what comes out when we use them.

Closures are seen by some as a complex and difficult concept to learn. We’ll blast that myth away in this lesson and learn how easy they are to use.

The prototype is a special object that has a huge significance for JavaScript inheritance. Prototypes are a powerful mechanism, and it is important to understand them well.

The spread syntax is a concise way to expand an array or other iterable into an arbitrary number of function arguments or array elements.

A great use of the spread syntax is for common array operations like cloning, concatenation, etc.

In this lesson, we can take a look at two additional function features, both to do with parameters: default parameters and rest parameters.

JavaScript has built-in support for destructuring arrays and objects into individual variables during assignment. This is a real time-saver. In this lesson, I’ll show you how to do this, as well as how to destructure parameters in function calls.

Destructuring makes it easy to break an array or object out into individual variables.

AJAX (Asynchronous JavaScript and XML) is a cornerstone of modern web apps, allowing them to fetch data from the server and display it on the page without needing to refresh or reload the entire page. We’ll explore AJAX in detail in this lesson.

Regular expressions are an extremely powerful way to find strings in text based on patterns. They can be extraordinarily complex—almost a programming language unto themselves—but they can also be extremely useful.

There’s still a lot to learn about regular expressions. In this lesson, we’ll learn some advanced features of regular expressions, including matching and replacing strings.

That’s not all! Regular expressions are a (simple) programming language in their own right. We’ll explore them further in this lesson. 

Classes in JavaScript are a syntactic sugar that makes it easier to use JavaScript’s prototype-based inheritance. In this lesson, we’ll focus on the way to create objects and deal with inheritance.

This simple rectangle class knows how to calculate its own area:

If you want to run some code after a timed delay, or want to run code at a regular interval, you will need setTimeout() or setInterval().

ECMAScript Modules (ES Modules or ESM for short) are one of the greatest features of JavaScript to emerge in recent years. In this lesson, I’ll show you how to make use of them for more modular, maintainable JavaScript.

In this lesson I’ll show you the different DOM methods we can use to select elements from the page so that we can work with them programmatically.

In this lesson we’ll take a look at the basic APIs for working with HTML elements and their attributes, working with elements that we have previously selected.

In this lesson we’ll see how to traverse from one DOM node to another with code. This will help us map out the structure of the page and understand its contents.

As well as manipulating elements, we might want to add new ones or remove existing ones. In this lesson we’ll look at the methods we can use to do this.

We can create a number of different things, such as elements, attributes, and comments, using the document interface. We can also create a lightweight version of a document called a documentFragment. This lets us manipulate elements in memory, improving performance. We’ll look at these topics in this lesson.

DOM events are extremely important. They are what allow us to create compelling, interactive web pages. We’ll see how to use DOM events to react to user and browser events in this lesson.

The selector API allows us to select elements from the page using CSS selectors, much like in popular JavaScript libraries such as jQuery.

Where in the world are you? The Geolocation API can tell you this, even in non-mobile environments like desktop computers. That’s what we’ll focus on in this lesson.

With this code, you can retrieve and log the user’s position—with their permission, of course!

There are several different ways in which we can store data between browser sessions, including localStorage, Web SQL, and IndexedDB. In this lesson, we’ll look at how we can use each of these technologies, and when each might be useful.

Web workers provide a way for us to offload complex processing to a worker thread to avoid blocking the main UI thread. In this lesson, we’ll see how to use dedicated workers.

In this lesson we’ll look at native JavaScript promises, a special type of object that represents an operation that hasn’t completed yet, but which is expected at some point.

In this lesson we continue looking at promises, this time focusing on handling multiple asynchronous tasks with promise chaining.

What if you want to wait on a number of promises? If you want to wait until all the promises have resolved, you can use the Promise.all() method. Or, if you want to just wait until any of them have resolved, use Promise.any().

The async keyword is a recent addition to the JavaScript language to make concurrent programming with promises even easier to write and read. In this lesson, we’ll learn about the async keyword, including where we can use it and what happens when we do.

In this lesson we’ll move on to look at the async keyword’s companion, the await keyword, which can only be used within async functions.

Let’s put async and await through their paces by using multiple awaits in a single async function, and catching errors with try...catch.

Another cool thing you can do with async is to code asynchronous iteration with async generators.

Ordinarily, an import statement is static—it’s evaluated when the JavaScript file is first loaded, so your code doesn’t have any control over whether the import is run, and you can only use static strings for the module name.

Dynamic imports change all that, though. They are evaluated as needed, so you can delay importing a module until you know it’s needed, and you can use dynamic module names.

Here’s how to load a different module depending on whether the code is running on the client or server. 

Congratulations on completing this course! Along the way, you’ve learned a lot about JavaScript: from the basics of the language to new features that have been added in recent years. Treat this course as a firm foundation to continue building your knowledge. 

By the end of this course, you will understand concepts like first-class functions, immutability, composing functions, currying, and even how to work with the DOM in a functional way.

In this course, you’re going to learn the basics of JavaScript from a web designer’s perspective. Along the way, we’ll build some examples that are geared towards what you as a web designer might face on a daily basis.