A Complete Beginners Guide To Javascript — Part 1

Will Swan
Level Up Coding
Published in
38 min readJun 29, 2019

--

This is the first of two stories where you will learn everything you need to know to start programming using Javascript.

To learn about Javascript for the DOM and web, check out part 2

So what does the story include? I have split it up into the following sections covering the basics of Javascript:

  • Introduction
  • Variables
  • Assignment
  • Data Types
  • Functions
  • Strings
  • Numbers
  • Arrays
  • Objects
  • Dates
  • Arithmetic & Math
  • Conditions & Comparisons
  • Loops
  • Errors
  • Classes
  • Asynchronous Programming

I recommend following along with this story using something like PlayCode.io so that you can really get a grasp on everything that we go through.

Introduction

Let’s start by talking about what Javascript is and why it is so important. Created in 1995, Javascript is a programming language designed for the World Wide Web and is now used by the vast majority of websites. It enables us to create interactive web apps which when done right can give the end users a much more efficient, user-friendly, and enjoyable experience.

Javascript has become quite a powerful language over the years, and with lots of frameworks available, you can do pretty much anything you can think of. You can even now use Javascript for your back-end using NodeJS, build iOS & Android apps using frameworks like ReactNative, and build cross-platform desktop apps using frameworks like Electron.

Now we have talked a bit about what Javascript is and why it is useful, let’s have a look at some basic syntax.

We will start with comments, these are very useful and help not only organise your code but also help both you and other developers understand what is going on.

We can write single line comments using two forward slashes:

// This is a single line comment

We can also write multi-line comments:

/*
This is a
multi-line
comment
*/

Next, we have variables, these are used to hold data. Variables can be declared using three keywords, var, let and const:

var variableName;
let variableName;
const variableName;

var, let and const are all keywords, this means that they are used to define what action is to be performed. With var, let and const we are telling the browser to create variables.

Variable names cannot start with a number, typically you will see them start with either a lower case letter or an underscore. In Javascript, we use what is called Camel Case for pretty much everything, including variable names. This is where the first word starts with a lower case letter and then every word that follows starts with an uppercase letter.

This means that instead of:

variable_name
variable-name
VariableName

We use:

variableName

Javascript is also case sensitive, so variableName is not the same as VariableName.

Next, we have literals, these are simply fixed values. For example:

20
"Hello World"

Now let’s have a quick look at operators, these are symbols which allow you to do things like assignment, arithmetic, and comparisons. For example, if we wanted to assign the value 20 to a variable, then we would use the equals operator.

let variable = 20;

Or maybe we wanted to multiply 20 by 5, for this, we would use the multiplication operator which is an asterisk.

20 * 5

With our multiplication, what we have just written is called an expression. An expression is a mixture of things like literals, variables, functions, and operators which when combined are used to compute a single value. With 20 multiplied by 5, we are combining the literals 20 and 5 with the multiplication operator to compute the value 100.

This is the basic syntax of Javascript now covered, let’s now have a look at variables in more detail.

Variables

As I mentioned earlier, we have three ways of declaring variables in Javascript, var, let and const. So what is the difference between them?

var and let are both mutable, this basically means that we can change their value. const on the other hand, is immutable, think of this as being read-only, so the value cannot be changed. For example:

// This will work
var animal = "dog";
animal = "cat";
// This will work
let animal = "dog";
animal = "cat";
// This will not work
const animal = "dog";
animal = "cat";

So if var and let are both mutable, then what is the difference between them? Well, they basically have different scopes. This means that the ability to access them differs depending on where you are in a script, var is function scoped,let and const are both block scoped. This means that var can be accessed throughout an entire function whereas let and const are only available within the block that they were declared in. A block is anything within the braces.

Let’s have a look at an example:

// Var
for (let i=0; i<1; i++) {

var animal = "dog";
let country = "England";
const planet = "Earth";
}// This will log "dog"
console.log(animal);
// These will both throw errors
console.log(country);
console.log(planet);

When trying to log the country and planet variables you would see an error, this is because we are trying to access them from outside of the block that they were declared in.

You might now be wondering why this works, looking at the code you might think that the var would also only available inside the block because that is where it was declared. It works because of a thing called Hoisting. What Javascript does is during the creation phase it initialises the var at the beginning of the function with a value of undefined. The value you want then gets assigned when that line of code is run. As we are still in the same function we can access animal from outside of the block because it has actually been defined before the block. This can be a bit confusing at first, but the more you write Javascript the more you will understand.

In Javascript, we aren’t required to assign a value when we declare the variable, for example, we could declare animal like this:

let animal;

Now even though we haven’t assigned a value to it, it does still hold a value, and that value is undefined. We can even declare multiple variables at once:

let animal, country, planet;

Now that we know a bit more about variables, let’s move on to assignment.

Assignment

Assignment is basically what it says, it is the process of assigning a value to a variable. We have already looked at assigning literals to variables:

let animal = "dog";

We can also assign variables to other variables:

let animalOne = "dog";
let animalTwo = animalOne;

Here both animalOne and animalTwo equal "dog".

In Javascript, we have a few quick ways of updating the value of a variable. For example, let's say we have a variable with the value "Hello" and we want to add "World" to that variable. To do this all you have to do is:

let myVar = "Hello";
myVar += " World";

What we have done here is called concatenation, this is where two or more values are joined together into one value. In our case "Hello" and " World" have become "Hello World".

What happens if we try and concatenate two numbers? Well, they are added together instead of joined. For example:

let myVar = 1;
myVar += 1;

Here myVar now equals 2, instead of 11. When working with numbers we can also quickly subtract, multiply, divide, increment and decrement in the same way as we have just added.

let myVar = 1;// Increment
myVar++; // myVar now equals 2
// Multiple
myVar *= 5; // myVar now equals 10
// Divide
myVar /= 2; // myVar now equals 5
// Subtract
myVar -= 2; // myVar now equals 3
// Decrement
myVar--; // myVar now equals 2

That is all you need to know about assignment, so let’s now have a look at data types.

Data Types

We now have a good understanding of variables and assigning values to those variables so let’s dive a bit deeper into the data types that our variables can hold.

We already know about strings and numbers. One quick thing to note about strings though is that they can be encapsulated in either single or double quotes, for example:

'my string'
"my string"

The next simplest data type is a boolean, this is basically either true or false.

let loading = false;

With boolean variables we can assign the opposite value to a variable, for example:

let loading = false;
loading = !loading; // Loading now equals true

We can also assign a boolean based on a condition, for example:

let first = 4;
let second = 7;
let isEqual = (first === second);

Here isEqual equals false because our first variable does not equal our second variable.

Now let’s have a look at arrays. Arrays allow us to store multiple values in a single variable and are defined using square brackets.

let colours = ["red", "green", "blue"];

We don’t have to populate the array when we declare it, we could instead declare an empty array and populate it later. For example:

let colours = [];colours.push("red");
colours.push("green");
colours.push("blue");

Here we still end up with array just like the first one we created. To access the values that the variable is holding we use the index of the array. Arrays are zero-based, this means that the index starts from 0. For example:

console.log(colours[0]); // This logs red
console.log(colours[1]); // This logs green
console.log(colours[2]); // This logs blue

Our index doesn’t have to be a number though, it could also be a string, this is called an associative array. For example:

let user = [];
user["firstName"] = "Bob";
user["lastName"] = "Smith";
console.log(user["firstName"]); // This logs Bob
console.log(user["lastName"]); // This logs Smith

So far all of the arrays we have created have been one dimensional, this means there is just one list of values. Arrays can also be multi-dimensional, in other words, lists within lists.

let sequences = [];let sequence1 = [1,2,3,4,5,6];
let sequence2 = [1,1,2,3,5,8];
sequences.push(sequence1);
sequences.push(sequence2);

We have now created a two-dimensional array where we have a list containing lists of different sequences. We access values in the same way as before, the only difference being now we have two indexes instead of one. For example, let’s say we want to get the second number in the first sequence.

console.log(sequences[0][1]); // This logs 2

One thing to be aware of with multi-dimensional arrays is the more dimensions you add the total storage needed for the array increases dramatically. Because of this, you should use them wisely.

Let’s go back to associative arrays for a moment. Even though it is possible to create these kinds of arrays, you will rarely see them used in Javascript. The reason for this is because there is a far better way of doing it, and that is by using an object.

Objects are the backbone of Javascript, pretty much everything in Javascript is an object at its core. Objects are groups of key-value pairs, let’s create a user object.

let user = {
firstName: "Bob",
lastName: "Smith"
};

Here we have two keys, firstName and lastName, and two values, "Bob" and "Smith". The values can be any data type, even other objects, for example:

let user = {
name: {
first: "Bob",
last: "Smith",
},
age: 30,
isActive: true,
favouriteColours: [
"red",
"green",
"blue"
]
};

We access objects just like arrays, except for instead of an index we use the keys.

console.log(user.age); // This logs 30
console.log(user.name.first); // This logs Bob
console.log(user.favouriteColours[0]) // This logs red

It is as simple as that, you will most likely find yourself using objects a lot when writing Javascript. One convenient feature of objects is the ability to have a function as the value. For example, we could write a function which returns both the first name and last name of the user.

let user = {
firstName: "Bob",
lastName: "Smith",
fullName: function() {
return `${this.firstName} ${this.lastName}`;
}
};

Now if we logged user.fullName() we would get "Bob Smith". You will see here that we have used a few things that we haven’t covered yet, functions we will cover later on in this story. The other two things are the this keyword and strange ${} syntax. Firstly, this is a keyword used to access values from itself, so here it is accessing the values from our user object. The strange syntax is something called a template literal, this basically allows us to use variables within strings. Template literals are one of my favourite features of Javascript, we used to have to use the + operator to achieve what template literals can do. For example:

let first = "Hello";
let second = "World";
let third = "!";
// Old Way
let oldString = first + " " + second + third;
// New Way
let newString = `${first} ${second}${third}`;

Both oldString and newString both hold the exact same values but newString was created in a much simpler and easier to read way. One of the major benefits of template literals is the ability to create multi-line strings.

The last thing we will look at with data types is the typeof() function, this allows you to find out what data type the value is and can be very useful. For example:

console.log(typeof("Hello")); // This logs string
console.log(typeof(1)); // This logs number
console.log(typeof(true)); // This logs boolean
console.log(typeof(function() {})); // This logs function

Now we have a good grasp on data types, let’s have a look at functions.

Functions

Functions are blocks of code that are specifically written to perform a single task. They are great for splitting up your code so that it is easier to read, they also allow for reusability of code without copying and pasting every time you need to perform a specific task. Let’s have a look at how to write one.

function sayHello() {
console.log("Hello World");
}

In Javascript, we use the function keyword to declare a function, followed by the name of the function with brackets after it. To call a function simple type the name of the function followed by the brackets.

sayHello(); // This will log "Hello World"

If we wanted to, we could assign our function to a variable.

let sayHello = function() {
console.log("Hello World");
}

If we are assigning our function to a variable then we don’t need the function keyword, instead we can use arrow functions.

let sayHello = () => {
console.log("Hello World");
}

All of these functions execute in the same way and are called in the same way. Sometimes we may want our function to execute without us calling it though, to do this we use an immediately invokable function expression or IIFE for short. These are written like so:

(function () {
console.log("Hello World");
})();

Just like with assigning a function to a variable, we can also get rid of the function keyword here if we want to.

(() => {
console.log("Hello World");
})();

Both of these work in the same way, one just doesn’t have the function keyword.

One of the main things you will want to do with a function is to pass data to it, we do this using parameters. The parameters that a function accepts are defined within the brackets directly after the function name. For example, let’s create a function that combines two strings together.

function combineStrings(first, second) {
let result = `${first} ${second}`;
}
combineStrings("Hello", "World");

This function uses the two strings that we have passed in to create a new string. There is an issue though, currently, we can’t get the new string. To get the new string we need to return it from the function, this is done using the return keyword.

function combineStrings(first, second) {
return `${first} ${second}`;
}
let newString = combineStrings("Hello", "World");

Now if we were to log newString then we would get "Hello World". This is a function at its most basic, functions can be as complex as you want them to be. Let’s have a look at some other options we have for parameters, for example, what if we don’t know how many strings are going to be passed into the function. This isn’t a problem, we can use the ... syntax to turn all passed parameters into an array, for example:

function combineStrings(...strings) {
// This logs ["Hello","World","!"]
console.log(strings);
}
combineStrings("Hello", "World", "!");

Maybe we aren’t even sure if a parameter is going to be passed, for this we can use default values. These are written like so:

function doSomething(param1 = "Default", param2 = 34, param3 = false) {}// doSomething will use "Hello", 34, false
doSomething("Hello");
// doSomething will use "Hello", 100, false
doSomething("Hello", 100);
// doSomething will use "Hello", 100, true
doSomething("Hello", 100, true);

The last thing we will look at with functions is that they can call themselves, let’s have a look at how that works:

function increment(count = 0) {  // Log count
console.log(count);
// Increment
count++;
// If count equals 1then increment again
if (count === 1) {
increment(count);
}
}increment();

If you run this function you will get two logs, 0 and 1. You need to be very careful with functions calling themselves if you are not then you could end up in an infinite loop of the function calling itself over and over again.

There we have it, you now have a good understanding of functions. Next, we will have a look at a load of the cool things we can do with Strings.

Strings

Javascript has many convenient ways for working with strings. I won’t go through them all now, but I will go through the ones that I think you will make use of the most.

Let’s start with the length property, this does what it says on the tin.

let ourString = "Hello World!";// This logs 12
console.log(ourString.length);

Now let’s say that we want to know if our string includes an exclamation mark, to do this we use the includes method.

let withMark = "Hello World!";
let withoutMark = "Hello World";
// This logs true
console.log(withMark.includes("!"));
// This logs false
console.log(withoutMark.includes("!"));

So we now know if our string includes an exclamation mark, maybe we don’t want it to. To get rid of the exclamation mark we can use the replace method, this takes two parameters. The first parameter is what we are searching for, and the second is what we want to replace the search with.

let ourString = "Hello World!!";// This logs "Hello World!"
console.log(ourString.replace("!", ""));

Here we are searching for the exclamation mark, and replacing it with an empty string. Now you will notice that the replace method has only removed one of the exclamation marks, this is because replace only searched for the first instance of the sub-substring. If we want to replace all instances of the exclamation mark then we will need to use two methods together, the split and join methods. The split method splits a string up into an array using a given parameter, this parameter is removed from the string. For example:

let ourString = "Hello World!!";// This logs ["Hello World", "", ""]
console.log(ourString.split("!"));

That’s great, we have removed the exclamation marks. The only issue now is that is an array, not a string, to turn it back into a string we use the join method. Just to note, join is an array method and not a string method, using it on a string will give you an error.

let ourString = "Hello World!!";// This logs "Hello World"
console.log(ourString.split("!").join(""));

Let’s look at that again with another example, let’s say we have a string which has the word single in it multiple times and we want to replace all instances of single with the world double.

let ourString = "single single single";// Split - this logs ["", " ", " ", ""]
console.log(ourString.split("single"));
// Join - this logs "double double double"
console.log(ourString.split("single").join("double"));

Now we now how to replace sub-strings, let’s say that we want to make everything uppercase. To do this we use the toUpperCase method, there is also a toLowerCase method which works in the opposite way.

let ourString = "hello world";
let upperCase = ourString.toUpperCase();
let lowerCase = upperCase.toLowerCase();
// This logs "HELLO WORLD"
console.log(upperCase);
// This logs "hello world"
console.log(lowerCase);

There is one last method that I want to show you, and that is the trim method. Let’s say that we have a user input and we want to process the value of it, this value might have unnecessary white space. The trim method allows us to remove all of that white space.

let badString = "     hello world     ";// This logs "     hello world     "
console.log(badString);
// This logs "hello world"
console.log(badString.trim());

There we go, those are what I think are the most useful and commonly used convenient ways for working with strings. Let’s now have a look at numbers.

Numbers

Let’s start by looking at some of the different ways you can write numbers in Javascript. Firstly, we have the obvious two, integers and floats. An integer has no decimal points, and a float has decimal points.

// Integer
8
// Float
8.4

Next we have the exponent notation. Say you want to use the number 76 million 200 thousand without typing out loads of zeros, you can just type it it’s exponential.

// This
762e5
// Instead of
76200000

You can also use negative exponentials, for example, 0.00762 would be 762e-5.

We can also write our number as a hexadecimal, for example, 161 would be 0xA1. I am not going to go into detail about hexadecimals and exponentials, those are topics for another more mathematics based story.

Now that we know a few ways in which we can write numbers, let’s say that we want to check if a value is a number, for this, we use the isNaN functions. NaN stands for not a number.

// This logs false
console.log(isNaN(1));
// This logs false
console.log(isNaN(1.6));
// This logs false
console.log(isNaN(762e5));
// This logs false
console.log(isNaN(0xA1));
// This logs false
console.log(isNaN(true));
// This logs false
console.log(isNaN("1"));
// This logs true
console.log(isNaN("1A"));

Most of the results you would expect, but why do true and "1" also, log false. true logs false because a boolean is basically a 1 or a 0, so true is actually 1. What the isNaN function does is it first converts the parameter to a number and then works out whether it is an actual number. This functionality explains why "1" returns false, because if you convert "1" to a number then it equals 1.

Next, let’s have a look at the methods available for changing the format of a number:

let ourNumber = 1376.89;// This logs "1376.89"
console.log(ourNumber.toString());
// This logs "1.37689e+3"
console.log(ourNumber.toExponential());
// This logs "1.4e+3"
console.log(ourNumber.toExponential(1));
// This logs "1377"
console.log(ourNumber.toFixed());
// This logs "1376.890000"
console.log(ourNumber.toFixed(6));
// This logs "1376.89"
console.log(ourNumber.toPrecision());
// This logs "1376.9"
console.log(ourNumber.toPrecision(5));

We can also do the opposite and turn these formatted strings back into a number using Number().

let ourNumber = 1376.89;// This logs 1376.89
console.log(Number(ourNumber.toString()));
// This logs 1376.89
console.log(Number(ourNumber.toExponential()));
// This logs 1400
console.log(Number(ourNumber.toExponential(1)));
// This logs 1377
console.log(Number(ourNumber.toFixed()));
// This logs 1376.89
console.log(Number(ourNumber.toFixed(6)));
// This logs 1376.89
console.log(Number(ourNumber.toPrecision()));
// This logs 1376.9
console.log(Number(ourNumber.toPrecision(5)));

And there we have it, that is all you need to know about numbers as a beginner to Javascript. Let’s now move onto learning a bit more about arrays.

Arrays

We have already had a look at how to declare and access arrays, now let’s have a look at one of the most common things you will do with an array, iterate over it. In Javascript, there are three easy ways to loop through an entire array. We will start with the for loop.

We can write our for loop in two different ways, we will first look at the older way of writing them. We start by declaring a count variable, we then define how many times the loop will run which in this case is the length of the array, and lastly, we increment our count on every iteration.

let colours = ["red","green","blue","purple","yellow"];for (let i=0; i<colours.length; i++) {
console.log(colours[i]);
}

What we have just written will loop through each item of the array and log it to the console. The older syntax is bit cumbersome and can lead to annoying bugs, for example, if you accidentally tell it to loop the wrong number of times. Now we are able to write this same loop in a simpler way like so:

let colours = ["red","green","blue","purple","yellow"];for (colour of colours) {
console.log(colour);
}

This does the exact same thing, but it looks a lot cleaner. While for loops do have their uses, for example, if you want to run asynchronous code inside the loop, we have two other great ways of iterating over arrays. forEach and map are two array methods, and they are both written in the same way.

let colours = ["red","green","blue","purple","yellow"];colours.forEach((colour) => {
console.log(colour);
});
colours.map((colour) => {
console.log(colour);
});

Both of these methods take a function as the parameter, and that function has the array item as a parameter. We could also add two other parameters to our function, an index parameter, and an array parameter, but I won’t go into these now.

At this point, you are probably wondering what is the point of having both the forEach and map methods when they both look pretty much identical and seem to do the exact same thing. It is true that they are very similar, map can do everything that forEach can do, but forEach can not do everything that map can do. The difference is that forEach doesn’t return anything whereas map does return a value.

Because of this, forEach is used for when you don’t want to modify the array, for example, you just want to display the values in it, or save each item to storage. map is used when you do want to modify the array, for example replaces values in the array. Let’s have a look at this in action by adding the word colour to the colour itself.

let colours = ["red","green","blue","purple","yellow"];let mapColours = colours.map((colour) => {
return `${colour} colour`;
});
let forEachColours = colours.forEach((colour) => {
return `${colour} colour`;
});
// This logs ["red colour", "green colour", "blue colour", "purple colour", "yellow colour"]
console.log(mapColours);
// This logs undefined
console.log(forEachColours);

I said that map can do everything that forEach can do but you should only use it if you are modifying the array. You might be thinking why should I only use it for modifying the array. The reason is that map will create a new array even if you aren’t returning anything, as programmers this is something that we don’t want because our code should be as fast and efficient as possible.

Let’s have a look at how we can add items to an array, the first way is by adding the value directly to an index.

let numbers = [1,2,3,4];
numbers[4] = 5;
// This logs [1,2,3,4,5]
console.log(numbers);

While it is possible to do it this way, I don’t recommend it. If you get the index wrong then you could overwrite a value or create gaps in the array, both of these scenarios are most likely not desired. Let’s have a look at these scenarios:

let numbers = [1,2,3,4];// Overwrite
numbers[2] = 5;
// This logs [1,2,5,4]
console.log(numbers);
// Gap
numbers[9] = 5;
// This logs [1,2,3,4,undefined,undefined,undefined,undefined,undefined,5]
console.log(numbers);

The better way to add items to an array is by using the push method like we used earlier in this story. With push, the value you want to add will always be added at the end of the array.

let numbers = [1,2,3,4];
numbers.push(5);
// This logs [1,2,3,4,5]
console.log(numbers);

We can also add values to the start of the array, to do this we use the unshift method.

let numbers = [1,2,3,4];
numbers.unshift(5);
// This logs [5,1,2,3,4];
console.log(numbers);

But what if we want to add a value, or multiple values, somewhere in the middle of the array. We can do this by using the splice method, this takes a few parameters. The first parameter is the index where the new items should be inserted. The second is how many items should be removed. Lastly, the rest of the parameters are the values which you want to add.

let numbers = [1,2,3,4];numbers.splice(2, 0, 5);// This logs [1,2,5,3,4];
console.log(numbers);
numbers.splice(2, 1, 8, 9);// This logs [1,2,8,9,3,4];
console.log(numbers);

Great, we can add values anywhere we want in the array. Now what about if we want to delete values. We have three ways of doing this, pop, shift, and splice. Let’s start with pop, this method removes the last index of the array.

let numbers = [1,2,3,4];
numbers.pop();
// This logs [1,2,3]
console.log(numbers);

The shift method removes the first index of the array.

let numbers = [1,2,3,4];
numbers.shift();
// This logs [2,3,4]
console.log(numbers);

Lastly, splice works in the same way as before except this time we aren’t adding any values.

let numbers = [1,2,3,4,5];numbers.splice(2, 1);// This logs [1,2,4,5]
console.log(numbers);
numbers.splice(1,2);// This logs [1,5]
console.log(numbers);

And there we have, you can now declare, add, remove, and iterate over arrays. Before we finish with arrays let’s quickly go through some very useful array methods.

Firstly, we have the toString method, this simply returns a comma separated string of the array.

let numbers = [1,2,3,4];// This logs "1,2,3,4"
console.log(numbers.toString());

Next, we have the reverse method, this does what you would expect, it reverses the array.

let numbers = [1,2,3,4];// This logs [4,3,2,1]
console.log(numbers.reverse());

After that, we have the includes method, this works just like it does with strings, it allows us to see if an array has a value.

let numbers = [1,2,3,4];// This logs true
console.log(numbers.includes(2));
// This logs false
console.log(numbers.includes(5));

Now we have a very handy method for joining to arrays together, this is the concat method.

let numbers1 = [1,2,3,4,5];
let numbers2 = [6,7,8,9,10];
let numbers = numbers1.concat(numbers2);
// This logs [1,2,3,4,5,6,7,8,9,10]
console.log(numbers);

Let’s say we have an array of numbers and we want to work out a sum of all the numbers, for example subtracting them all from each other. To do this sum we can use the reduce and reduceRight methods. The difference between these methods is reduce starts from the first index, and reduceRight starts from the last index.

let numbers = [23,32,54,79];let reduce = numbers.reduce((total, number) => {
return total - number;
});
let reduceRight = numbers.reduceRight((total, number) => {
return total - number;
});
// This logs -142
console.log(reduce);
// This logs -30
console.log(reduceRight);

I chose to subtract all of the numbers because it enables you to clearly see that reduce produces a different result than reduceRight because it started from the first index instead of the last one. You can see that both of these methods take a function as a parameter and that this function has two parameters, the total of the sum and the current value of the array.

Now let’s say that we want to sort an array in ascending order, to do this we use the sort method. Similarly to the previous methods, sort also takes a function as a parameter, this function contains the logic for the sorting. The function that we pass has two parameters, a and b, these are the current and next values.

let numbers = [12, 97, 32, 56, 63];let sortedNumbers = numbers.sort((a, b) => {
return a - b;
});
// This logs [12, 32, 56, 63, 97]
console.log(sortedNumbers);

Great, we now have a sorted array, but how does this work? Why do we subtract a from b?

We subtract a from b because if we return a negative number then a is sorted before b. If we wanted to sort the numbers in descending order then we would do b — a, because we would want b to be sorted before a. This can take a little bit to get your head around, I know it took me a little while, so let’s have a look at it in a bit more detail.

Let’s say we have an array with 2 values:

[value1, value2]

With the comparison a — b:

a(value1) - b(value2)

With this comparison we have three possible outcomes, a positive number, a negative number, and zero. Positive numbers mean that b will be sorted before a:

value2, value1

Negative numbers mean that a will be sorted before b:

value1, value2

And zero means that no change is necessary:

value1, value2

So with the same comparison if we have 3 and 4, then it will sort to [3, 4]:

[3, 4] -> (3 - 4 = -1) -> [3, 4]

If we have 4 and 3, then it will sort to [3, 4]:

[4, 3] -> (4 - 3 = 1) -> [3, 4]

And lastly, if we have 4 and 4, then it will sort to [4, 4]:

[4, 4] -> (4 - 4 = 1) -> [4, 4]

One last time, this time with [3,1,1,5]:

// First pass
[3, 1, 1, 5] -> (3 - 1 = 2) -> [1, 3, 1, 5] // 3 & 1 swap
[1, 3, 1, 5] -> (3 - 1 = 2) -> [1, 1, 3, 5] // 3 & 1 swap
/*
At this point the array is sorted, but the algorithm requires one full pass with no swaps to know that it is sorted.
*/
[1, 1, 3, 5] -> (3 - 5 = -2) -> [1, 1, 3, 5] // No swap// Second pass
[1, 1, 3, 5] -> (1 - 1 = 0) -> [1, 1, 3, 5] // No swap
[1, 1, 3, 5] -> (1 - 3 = -2) -> [1, 1, 3, 5] // No swap
[1, 1, 3, 5] -> (3 - 5 = -2) -> [1, 1, 3, 5] // No swap

The algorithm has now completed a full pass with no swaps so it knows that the array is fully sorted. I have gone into this in quite a lot of detail because it is important when sorting arrays to know how it works, otherwise you aren’t able to use the sort method to it’s full capabilities. The type of sorting which we have just used is called Bubble sorting, if you want to know more about the different types of sorting and visually see how they work then I highly recommend playing around with SortingJS.

Okay, so lastly we are going to have a look at the filter method. This method allows us to filter out values from an array based on a condition. For example, lets say we want every number which is greater than 50.

let numbers = [12, 32, 43, 56, 72, 98];let filteredNumbers = numbers.filter((number) => {
return number > 50;
});
// This logs [56, 72, 98]
console.log(filteredNumbers);

Filtering arrays is as simple as that. Right, let’s now move on to have a look at objects in more detail.

Objects

We have already covered most of what you need to know about objects. We have looked at how to declare an object, how to assign values to them, and using functions as object values. The values of an object can also use the same convenient methods that we have just been looking at, for example, if your object has a string value, you could use toUpperCase() to format it. There are only three more things that I want to show you with objects, these are getters, setters, and constructors.

Let’s start with getters, these are functions inside of your object that allow you to get a value. Typically you would use these if you want to do some formatting to the value you are getting. For example, let’s say we have an object which is holding the total of a shopping basket.

let basket = {
total: 0
};
// Displays £0.00
console.log(`£${basket.total.toFixed(2)}`);

Without using a getter we would have to write something like this to display the total in a way that users are used to seeing. I am sure that you can imagine that this would be a pain to have to write wherever you want to display the total, so instead we will use a getter.

let basket = {
total: 0,
get totalPrice() {
return `£${basket.total.toFixed(2)}`;
}
};
// Displays £0.00
console.log(basket.totalPrice);

Now all we have to do is write basket.totalPrice whenever we want to get the formatted total. Setters, on the other hand, allow us to easily set a value in an object, let’s say we have an object where we want the value to be formatted when it is set, for example, a username that we want to be lowercase.

let user = {
username: "",
set setUsername(value) {
this.username = value.toLowerCase();
}
}
user.setUsername = "MYUSERNAME";// Logs "myusername"
console.log(user.username);

Both of these examples are very basic uses of setters and getters, typically you will do more with them than what we have done, but these show you in a simple way what they do and how to use them.

Let’s now have a look at constructors, these are incredibly handy. When developing there will most likely come a time where you need multiple objects to use the same structure. Of course, you could manually write the structure for each object just like we have been doing, or you could use constructors. Constructors are basically functions which create objects, for example, let’s say we want a user object for multiple users.

// Constructor
function User(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = function () {
return `${this.firstName} ${this.lastName}`
};
};
// First user
let firstUser = new User("Bob", "Smith");
// Second user
let secondUser = new User("Jill", "Summers");
// Logs "Bob Smith"
console.log(firstUser.fullName());
// Logs "Jill Summers"
console.log(secondUser.fullName());

Here you can see we have two user variables which are both using the same object structure. Just like regular functions, our constructor could have default values if we don’t want to pass in values when creating the object, for example:

function User(name, online = true) {
this.name = name;
this.online = online;
};
let myUser = new User("Bob Smith");// This logs {name: "Bob Smith", online: true}
console.log(myUser);

Once you have created your object, you then use it just like you would any other object. That is now everything you need to know about objects as a beginner to Javascript. Let’s now have a look at working with dates.

Dates

Javascript has an in-built object for working with dates, the Date object. Let’s start by just getting the current date and time.

// This logs Sat Jun 29 2019 15:40:17 GMT+0100 (BST)
console.log(new Date());

Obviously, if you run this then you will get a different log but it will be in the same format:

DayName Month Day Year Hour:Minute:Second Timezone (TimezoneName)

Most of the time we probably don’t want all of this information, we can use the Date objects built-in methods to get any of the bits that we want.

// This logs 2019
console.log(new Date().getFullYear());
// This logs 5
console.log(new Date().getMonth());
// This logs 29
console.log(new Date().getDate());
// This logs 6
console.log(new Date().getDay());
// This logs 15
console.log(new Date().getHours());
// This logs 45
console.log(new Date().getMinutes());
// This logs 56
console.log(new Date().getSeconds());
// This logs 129
console.log(new Date().getMilliseconds());

By default these methods will return the date using the timezone of the browser, we might not want that. Instead we might the UTC date and time, this is as easy as adding UTC after get in the method names.

new Date().getUTCFullYear();
new Date().getUTCMonth();
new Date().getUTCDate();
new Date().getUTCDay();
new Date().getUTCHours();
new Date().getUTCMinutes();
new Date().getUTCSeconds();
new Date().getUTCMilliseconds();

Another common task that you will probably need to do at some point is to get the number of milliseconds since the EPOCH, this is the 1st January 1970 at midnight UTC. We have two different ways of getting the time since the epoch.

// This logs 1561820006430
console.log(new Date().getTime());
// This logs 1561820006430
console.log(Date.now());

You can see that they both return the same value, I personally use Date.now(), but it is up to you which method you choose. That is basically all you need to know at the moment. Working with dates can get pretty complex and messy in Javascript, most of the developers that I know use third-party packages to format, and use dates.

Arithmetic & Math

We have already looked at basic addition, subtraction, multiplication, and division, we have also covered incrementing and decrementing variables. Let’s now have a look at the modulus operator, this is used for getting the remainder of a sum, for example:

// This logs 3.7
console.log(8 % 4.3);

This can be handy, for example, if you wanted to know if a number was even or not.

// This logs true because 4 is even
console.log((4 % 2 === 0));
// This logs false because 3 is odd
console.log((3 % 2 === 0));

Next, we have the exponentiation operator, this use to multiple a number by the power of another number.

// This logs 4 - 2 squared equals 4
console.log(2 ** 2);
// This logs 64 - 4 cubed equals 64
console.log(4 ** 3);

Just like in school, Javascript does the multiplication and division before the addition and subtraction, for example:

// This logs 12
console.log(4 + 4 * 2);
// This logs 16
console.log((4 + 4) * 2);

In Javascript, we have a great object called the Math object, this allows us to do more advanced mathematics. I will quickly go through some of the methods that are available which you are most likely to use. I am not going to through all of them or go into detail though because that is for another more mathematical story.

// Calculate the square root of a given value
// This logs 4
console.log(Math.sqrt(16));
// Calculate a given value to the power of another
// e.g. 6 to the power of 8, or 6 * 6 * 6 * 6 * 6 * 6 * 6 * 6
// This logs 1679616
console.log(Math.pow(6, 8));
// Round a given value to the nearest integer
// This logs 8
console.log(Math.round(7.6));
// This logs 7
console.log(Math.round(7.3));
// Round a given value up to the nearest integer
// This logs 8
console.log(Math.ceil(7.3));
// Round a given value down to the nearest integer
// This logs 7
console.log(Math.floor(7.6));
// Generate a random float between 0 and 1
console.log(Math.random());
// Get the highest value in a given sequence
// This logs 7
console.log(Math.max(5,2,6,7,5,3));
// Get the lowest value in a given sequence
// This logs 2
console.log(Math.min(5,2,6,7,5,3));

The Math object also has a few constants for us to use, just like before I will quickly list them but not go into to much detail.

// This logs PI
console.log(Math.PI);
// This logs E (Eulers number)
console.log(Math.E);
// This logs the natural logarithm of 2
console.log(Math.LN2);
// This logs the natural logarithm of 10
console.log(Math.LN10)
// This logs the base 2 logarithm of E
console.log(Math.LOG2E);
// This logs the base 10 logarithm of E
console.log(Math.LOG10E);
// This logs the square root of 2
console.log(Math.SQRT2);
// This logs the square root of 0.5
console.log(Math.SQRT1_2);

And there we have it, you now know how to do mathematics in Javascript. Next, we will have a look at conditions and comparisons.

Conditions & Comparisons

We have two ways for making comparisons in Javascript, the if and switch statements. Let’s start with the if statement, this is written like so:

if (condition) {
code to be executed if the condition is true
} else {
code to be executed if the condition is false
}

An if statement can have multiple if conditions, for example:

if (condition) {} else if (condition) {} else if (condition) {} else {}

Now we know how to write an if statement, let’s have a look at how we write the conditions. In Javascript we have 9 comparison operators, let’s have a look at them one by one.

First, we have the equal to operator:

// This logs true because 3 does equal 3
console.log((3 == 3));
// This logs false because 3 does not equal 4
console.log((3 == 4));
// This logs true because 3 does equal '3'
console.log((3 == '3'));
// this logs true because "1" does equal true
console.log(("1" == true));

The first two conditions make sense, but why do the last two also pass? This is because the equals operator doesn’t care about the data type, to it the string "1" is the same as the number 1 which is also the same as true. If we want the data type to matter then we can use === instead of ==, for example:

// This logs true
console.log(("1" == true));
// This logs false
console.log(("1" === true));
// This logs false
console.log((1 === true));
// This logs true
console.log((true === true));

Next, we have the not equal to operator:

// This logs true
console.log((1 != 2));
// This logs false
console.log(("1" != 1));
// This logs true
console.log(("1" !== 1));

Here you can see that we can also add an extra = to the not equal to operator so that our data type matters.

Next, we have our less than, more than, less than or equal to, and more than or equal to operators.

// This logs true
console.log((10 > 5));
// This logs false
console.log((10 < 5));
// This logs true
console.log((5 >= 5));
// This logs false
console.log((6 <= 5));

And lastly we have the not operator, we use this to check if booleans are true or false, for example:

let exists = false;// This logs true because exists does equal false
console.log((!exists));
exists = true;// This logs false because exists doe not equal false
console.log((!exists));

That is all of the 9 comparison operators, let’s now put them into use in an if statement.

let exists = false;if (!exists) {
// Condition passed
} else {
// Condition failed
}

We can also add more than one comparison to our condition, our condition can then pass if either both of the comparisons are true or one of them is.

let exists = false;
let number = 5;
if (exists && number === 5) {
// This will not be executed
} else {
// This will be executed because neither of our comparisons passed
}
if (exists || number === 5) {
// This will be executed because our number does equal 5
} else {
// This will not be executed
}

You can even have conditions inside conditions, for example, let’s say we want to do something if a number is either between 0 and 10 or 20 and 30.

let number = 9;if ((number > 0 && number < 10) || (number > 20 && number < 30)) {
// This will execute because 9 is between 0 and 10
}
number = 23if ((number > 0 && number < 10) || (number > 20 && number < 30)) {
// This will execute because 23 is between 20 and 30
}
number = 15if ((number > 0 && number < 10) || (number > 20 && number < 30)) {
// This will not execute because 15 isn't between 0 and 10 or 20 and 20
}

You can see that this is quite messy, this is an example of where you might want to use else if, for example:

let number = 23;if (number > 0 && number < 10) {
// This will not execute
} else if (number > 20 && number < 30) {
// This will execute
} else {
// This will not execute
}

Now using else if the code is much easier to read and understand.

Okay, so now you should have a good understand of if statements so let’s have a look at switch statements. switch statements compare a value with a list of different cases, and if none of the cases match than a default case is executed. For example, let’s say that we want to turn a number into the day of the week.

let day = 5;switch(day) {  case 1:
console.log("Monday");
break;
case 2:
console.log("Tuesday");
break;
case 3:
console.log("Wednesday");
break;
case 4:
console.log("Thursday");
break;
case 5:
console.log("Friday");
break;
case 6:
console.log("Saturday");
break;
case 7:
console.log("Sunday");
break;
default:
console.log("Invalid Day");
};

In this example "Friday" will be logged, if we changed our day variable to 12 then "Invalid Day" would be logged. You will notice that after each log we have written the break keyword, this is so that once a case has matched the switch statement exits.

Lastly, with switch statements we can have multiple cases run the same code. Let’s say we want to know whether our day is a weekday or a weekend.

let day = 5;switch(day) {  case 1:
case 2:
case 3:
case 4:
case 5:
console.log("Weekday");
break;
case 6:
case 7:
console.log("Weekend");
break;
default:
console.log("Invalid Day");
};

Here we will see "Weekday" logged if day equals 1, 2, 3, 4, or 5, and "Weekend" logged if day equals 6 or 7. That is all you need to know about conditions and comparisons, we will now have a look at loops.

Loops

We have already covered loops in quite a bit of detail, we have looked at for, forEach, and map. We do have two more loops to have a look at though, these are while and do while loops.

Firstly, while loops run until a condition is met. For example, let’s say that we want to run the loop until a number equals 10.

let fingers = 1;while (fingers < 11) {
console.log(fingers);
fingers++;
}

Here our loop runs 10 times, each time adding one to finger. You have to be careful with while and do while loops because if your condition is never met then you will end up with an infinite loop which will crash your script.

do while loops work in a similar way to while loops except they execute the block once regardless of whether the condition has been met or not. For example:

let fingers = 1;while (fingers < 1) {
console.log(`Fingers: ${fingers}`);
fingers++;
}
let toes = 1;do {
console.log(`Toes: ${toes}`);
toes++;
} while (toes < 1);

If you run this code you will see that we get no logs from the fingers loop and we get one log from the toes loop. This is because even though 1 is not less than 1, the do while loop has executed the block once.

Errors

In Javascript, errors can be very confusing and difficult to understand exactly what is going wrong. For example, if you run this:

let date = Date().parse();

You will get an error that says something along the lines of:

error: TypeError: Date().parse is not a function. (In 'Date().parse()', 'Date().parse' is undefined)

This is actually one of the easier errors to decipher, it is basically just saying that there is no function called parse in Date(). The main thing here is that this will crash your script, this line may only be a small part of your script so having the whole script crash is not ideal. What we could do is put this line inside a try catch block, this way the script won’t crash and it can continue doing everything else it is meant to do.

try {
let date = Date().parse();
} catch(err) {
console.log('Error message');
}

Now if you run this, the script won’t crash and an error message will be displayed. This still might be what you want though, if the rest of your code relies on this one line then you may want the script to exit. To force the script to exit we can use the throw keyword.

try {
let date = Date().parse();
} catch(err) {
console.log('Error message');
throw err;
}

Now our error message will be logged and then the script will exit and log the detailed error. This method allows you to show a user-friendly error message to the user before exiting the script, this is much more user-friendly than just showing the original Javascript error.

When debugging Javascript you will come across 6 error types, let’s have a look at these so you understand what they mean.

SyntaxError

This is what it says on the tin, there is an error with your syntax.

ReferenceError

This means that an illegal reference has occurred, for example, a variable is being accessed from outside of its scope.

TypeError

This means that you are doing something you shouldn’t be with a specific data type. For example, if you try and call forEach on an object, this would give you a TypeError because forEach isn’t a valid method for objects.

RangeError

This means that a number is outside of a valid range. For example, if you tried to use the toPrecision method to give a float 30 decimals, this would give you a RangeError because toPrecision only allows numbers to have up to 21 decimals.

URIError

This means that an error has occurred in one of the URI handling functions, these are caused by malformed URI’s.

EvalError

Lastly, this means that an error has occurred in the eval function. EvalError isn’t one that you really need to worry about as newer versions of Javascript throw SyntaxErrors instead of EvalErrors.

Now that we know a but more about errors and how to handle them, let’s move onto classes.

Classes

Classes are similar to objects but more advanced. I will write a class and then we will go through it bit by bit.

class ScoreBoard {  constructor(...players) {    this.players = [];
players.forEach((player) => {
this.players.push({
name: player,
score: 0
});
}); } displayScores() { this.players.forEach((player) => {
console.log(`${player.name}: ${player.score}`);
});
} updateScore(playerName) { this.players.map((player) => { if (player.name === playerName) {
player.score++;
}
return player; }); }}let scoreboard = new ScoreBoard("John", "Lucy", "Steve");scoreboard.updateScore("Lucy");
scoreboard.updateScore("John");
scoreboard.updateScore("Steve");
scoreboard.updateScore("Steve");
scoreboard.updateScore("Steve");
scoreboard.updateScore("Lucy");
scoreboard.updateScore("John");
scoreboard.updateScore("Lucy");
scoreboard.displayScores();

Here we have written a class that handles the scoring of a simple game. First, we have the constructor, this is a function that is called whenever a new instance of the class is created. In our constructor we add all of the players to an array and gave them all an initial score of zero. Next we have a function to display the scores, all this does is loop through the players and log the scores. Lastly, we have a function which updates the score of a specific player, to do this we are using map to loop through all of the players. If the players name equals the name that we passed in then the score is updated.

Below the class, we create a new instance of the class and store it in a variable called scoreboard, we then add a few scores to the players, and lastly display those scores. Hopefully this example shows how useful classes can be for modularising your code. I think that the best way for you to learn more about classes and how they work is to take what I have written above and try adding more functionality to it.

Asynchronous Programming

Let’s say we want to execute a function but we don’t know how long that function will take to execute, how do we get the return value of the function? We used to use what are called callbacks, these are functions that are passed into another function which are then called on completion. Callbacks are a bit of a nightmare, things get very confusing very quickly. Now we have better ways of handling asynchronous tasks, let’s start with promises.

Let’s create a function that will return a promise.

function exists(value) {

return new Promise((resolve, reject) => {

setTimeout(() => {

if (value) {
resolve('Value is true');
} else {
reject('Value is false')
}

}, 2000);

});

}
exists(true).then((response) => {
console.log(response);
}).catch((err) => {
console.log(err);
});

Here our function, exists, returns a promise, this promise either resolves or rejects depending on the value that we pass into it. If we pass in true then the promise resolves, in other words, everything went well, and if we pass in false then the promise rejects, which in other words means error. When we call our function we have two other functions chained to it, then and catch. The then function will be called if the promise resolves, the catch function will be called if the promise is rejected. If you run this code you will see that our logs don’t appear until two seconds has passed, this is because we have used setTimeout to simulate something happening. If you had a network request in the function, then the logs wouldn’t appear until the request has completed.

We can also chain promises, for example, let’s call exists again.

function exists(value) {

return new Promise((resolve, reject) => {

setTimeout(() => {

if (value) {
resolve('Value is true');
} else {
reject('Value is false')
}

}, 2000);

});

}
exists(true).then((response) => {
console.log(response);
return exists(true);
}).then((response) => {
console.log(response);
}).catch((err) => {
console.log(err);
});

Now if we run this code we will see the log "Value is true" after two seconds, and then two seconds later we will see another log saying the same thing.

Promises can be very confusing at first, I know it took me a while to get my head around them, but the more you use them, the more you come to understand them. You also probably see how chaining multiple promises can get very messy and confusing, we actually have a much simpler way of dealing with this, and that is async-await.

With async-await we are able to define asynchronous functions which can await responses from other asynchronous functions. For example, let’s write the same thing using async-await.

function exists(value) {

return new Promise((resolve, reject) => {

setTimeout(() => {

if (value) {
resolve('Value is true');
} else {
reject('Value is false')
}

}, 2000);

});

}
async function getExists() {

let firstResponse = await exists(true);
console.log(firstResponse);

let secondResponse = await exists(true);
console.log(secondResponse);

}
getExists();

We still get our two logs, but this code is much cleaner and easier to read. The only thing we don’t have here is the ability to catch any errors, let’s add that in.

function exists(value) {

return new Promise((resolve, reject) => {

setTimeout(() => {

if (value) {
resolve('Value is true');
} else {
reject('Value is false')
}

}, 2000);

});

}
async function getExists() {

let firstResponse = await exists(true);
console.log(firstResponse);

let secondResponse = await exists(true);
console.log(secondResponse);

let errorResponse = await exists(false);

}
getExists().catch((err) => {
console.log(err);
});

We have now added a call to exists() with false so that the promise is rejected, we have also added catch() when we call the getExists function. Adding catch here will catch every error in the getExists function, this is great because all of our errors go to one place.

I think I will leave asynchronous programming there for this story, you should now have a basic understanding of how promises and async-await work. The best thing to do now is to practice using them, this will most likely help you get to grips with them quicker than reading about them in more detail.

Conclusion

If I have done my job right then you should now have a great understanding of the Javascript basics. Like with any new skill, practice makes perfect, and the more Javascript you write the better and more knowledgable you will become. If you have any questions then ask away and I will answer to the best of my ability.

In the next story, we will have a look at working with the DOM and how to use Ajax to make network requests asynchronously.

Part 2: https://medium.com/@willptswan/a-complete-beginners-guide-to-javascript-part-2-501ec89af76c

--

--