JavaScript Tutorial for Beginners

As I promised in my last article on JavaScript fundamentals, you can expect some beginner-friendly content on this blog along with some learning paths.

I strongly believe in practical application. Therefore, I will not bore you with facts, long theory, or rant about which parts of JavaScript I consider good or bad. This tutorial is all about getting our hands dirty and understanding how JavaScript works inside out.

Table of Contents

  1. Sit down in front of a computer!. Don't start this tutorial before sitting down comfortably in front of a computer.
  2. Comments. Learn how to create comments that help you remember what you wrote in your code.
  3. Your first JavaSCript line. Start writing JavaScript code on your own.
  4. Dealing with data. Use JavaScript like a calculator. Learn how to formulate conditions. Learn how to represent simple data.
  5. The let keyword. Learn how to store your data for future reference.
  6. The Object type. Construct composite data that describes different features of things in your world.
  7. Arrays. Create and maintain a list of data.
  8. Functions. Create functions that perform calculations on data.
  9. Types. Learn how to find out the type of data you stored. Are you dealing with a number? Some text? Is the value there at all?
  10. Some more operators. Enrich your code with more operators that help you change values, and help you formulate better conditions.
  11. Control structures. Learn how to branch off based on conditional statements. Learn how to repeat your code as many times as you want, by just writing down your code once.
  12. Exercises. Get many exercises and reference solutions to practice what you learned.

Sit down in front of a computer

If you are reading this article on a mobile device without access to a computer, I am warning you, it's not optimal usage of your time. I recommend that you save this article for later, and get back to it once you can follow the coding examples.

After the tutorial, you will see a lot of exercises. I encourage you to solve them to verify your knowledge.

Your First JavaScript Line

In software development, we often brag about executing a "Hello World!" program. In some languages like Java, it takes a lot to write Hello World to the standard output. In JavaScript, we get away with one single line:

You may ask, where can I execute this line?

If you are lazy, you can simply execute it below. Try it out:

/*---Type here:--->*/

If you typed the message console.log( "Hello World!" ), you can see the following evaluation:

The first value is a console log, which is a value written to the console by the console.log function.

The second value is undefined, symbolizing that the console.log function does not have a defined returned value. You don't have to understand what this means yet until the section on Functions. Until then, just accept that the undefined value will appear after your console log.

Notice your statement can span multiple lines. Press enter inside the expression to separate content into two lines. Reformat your code in the above code editor as follows:

As you can see, you can format JavaScript code in any way you want. The interpreter will not care about the redundant whitespace characters.

Experiment a bit more with the log. Instead of "Hello World!", write 5 + 2. You should see the following:

> symbolizes the input of the console.

As it is inconvenient to load my blog each time you want to write JavaScript, I will recommend a service you can use to execute JavaScript code: CodePen. In the above link, I prepared everything you need: a JavaScript editor and a console.

In the editor, type

Watch it appear in the console.

Congratulations! You managed to write Hello World! to the console twice. Let's see what we learned:

  • console.log writes a log message to the console
  • "Hello World!" is a string. One way to formulate a string is using double quotes. Mind you, 'Hello World!' is also a valid string notation in JavaScript
  • there is a semicolon at the end of the statement. The semicolon itself is optional, but I recommend using it

While reading this tutorial, I encourage you to keep CodePen open, and play around with the examples.

Later we will learn how to

  • execute JavaScript in our browser developer tools,
  • embed JavaScript in HTML pages,
  • execute JavaScript using node.js.


We often place comments in our code so that we know what it is doing.

JavaScript is similar to C++ and Java in its commenting style:

  • Everything between /* and */ is ignored by the interpreter
  • Everything after // on the same line is ignored by the interpreter.

The above two comments are interpreted as:

Everything else is ignored.

Why do we use comments? To avoid ending up in similar situations:

My other favorite is:

Source: StackOverflow

Summary: write readable code with good comments!

Dealing with data

Most programming languages help you create values that symbolize a number, a character in a text, or a longer text. You can also symbolize the concept of true and false values using booleans. You can also create values that symbolize the absence of a value. These values are all called primitive datatypes.

The name primitive does not come from a negative place. These datatypes are neither stupid, nor inferior to any other datatypes we use in JavaScript. The name primitive comes from their simplicity. The other datatypes you will learn later are composite, and they consist of many primitive datatypes.

In JavaScript, there are six primitive types:

  • boolean (true or false)
  • number (including integers like 1, -2, and floating point numbers like 1.1, 2e-3)
  • string ( '' or "", 'ES6 in Practice' or "ES6 in Practice" )
  • null type (denoted by null)
  • undefined (denoted by undefined)
  • Symbol (don't worry about them yet)

At the bottom of the console in CodePen, there is a line with a > sign. This is where you can enter JavaScript expressions. Let's try some. Enter the expression you see after the > sign. Then press enter. You can see the result appear on the next line.

Handling integers is straightforward. You have the four arithmetic operations ( +, -, *, /) available for addition, subtraction, multiplication, and division respectively.

The % operator is called modulus. a % b returns the remainder of the division a / b. In our example, 7 / 5 is 1, and the remainder is 2. The value 2 is returned.

The ** operator is called the exponential operator. 5 ** 2 is five raised to the second power.

Some more info on floating points. Due to the way how numbers are represented, 0.1 + 0.2 is not exactly 0.3. This is normal and occurs in most programming languages.

3.1e-3 is the normal form of 0.0031. Read it like the exact value of 3.1 times ten to the power of minus three. Although the form is similar to 3.1 * (10 ** -3), there are subtle differences. 3.1e-3 describes the exact value of 0.0031. 3.1 * (10 ** -3) describes a composite expression that needs to be calculated:

Floating point arithmetics does not even make it exact.

The division 0 / 0 or using mismatching types creates a special number called not a number or NaN.

The latter is interesting to Python users, because in Python, the result would have been 'ES6 in PracticeES6 in Practice'. JavaScript does not work like that.

There is another interesting type: infinity.

JavaScript registers very large numbers as infinity. For instance, ten to the power of 309 is represented as infinity. Division by zero also yields infinity.

Let's see some strings.

The plus operator concatenates strings. Concatenation means that you write the contents of two strings after each other.

Strings are immutable which means that their value cannot be changed. When concatenating two strings, the result is saved in a third string.

If any of the operands of plus is an integer, the result becomes a string. JavaScript automatically converts the operands of an operator to the same type. This is called automatic type casting:

Rules may become confusing, so don't abuse automatic type casting. Just know that you may have to explicitly cast a string to an integer to be able to add it to another integer:

All conversions work. The first relies on giving a sign to a numeric string which converts it to a number. Then 1+2 becomes 3. The second type cast is more explicit: you use Number to wrap a string and convert it to a number.

I recommend using the third option: Number.parseInt with a radix. parseInt converts a string into a number. The second argument of parseInt is optional: it describes the base in which we represent the number.

Arbitrary strings are often NaN. "2" in base 2 is 10. You can see how easy it is to convert a binary or a hexadecimal (base 16) string into a decimal number. Base 16 digits are 0123456789abcdef. The last 6 digits may also be upper case.

Number.parseInt recognizes the starting characters of a string as integer numbers, and throws away the rest:

The dot is not a character present in integer numbers, so everything after 1234 is thrown away by Number.parseInt.

You can also use Number.parseFloat to parse floating point. It parses the floating point number until the terminating space:

Let's see some booleans values. Booleans are either true or false.

We can compare two numbers with >, >=, ==, ===, <=, <. We will discuss the difference between == and === soon. For the rest of the operators, the result of the comparison is a boolean.

The ! operator negates its operand. True becomes false, and false becomes true.

A truthy value is a value v for which !!v is true. Example truthy values are: nonzero integers, strings containing at least one character.
A falsy value is a value w for which !!w is false. Example falsy values are: empty string, 0, null, undefined.

We can convert a value to a boolean by negating it twice: !!:

  • assuming v is truthy, !v becomes false. !!v becomes !false, which becomes true.
  • assuming w is falsy, !w becomes true, and !!w becomes false.

For values a and b, a == b is true if and only if both a and b can be converted to the same value via type casting rules. This includes:

  • null == undefined is true
  • If an operand is a string and the other operand is a number, the string is converted to a number
  • If an operand is a number and the other operand is a boolean, the boolean is converted to a number as follows: true becomes 1, and false becomes 0.

Don't worry about the exact definition, you will get used to it.

For values a and b, a === b is true if and only if a == b and both a and b have the same types.

The negation of == is !=. Read it as is not equal to.

The negation of === is !==.

Let me introduce the ternary operator to drive home a strong point about truthiness.

The value of a ? b : c is:

  • b if a is truthy
  • c if a is falsy

It is important to note the difference between 2 == true and !!2.

I have seen the nastiest bug in my life in a code, where a condition was in a format num == true. As I never felt like learning boring definitions, my lack of knowledge shot me in the foot, because I assumed the opposite conversion in 2 == true. I can save you some headache by highlighting this common misconception. In 2 == true, true is converted to 1, and not the other way around.

Null, undefined, and Symbols are primitive types.

Null represents an intentional absence of a primitive or composite value of a defined variable.

Undefined represents that a value is not defined.

A Symbol() is a unique value without an associated literal value. They are useful as unique keys, because Symbol() == Symbol() is false. At this stage, just accept that symbols exist. You don't have to use them for anything yet.

The let keyword

First of all, in the below example, you have to know that console.log may print any number of arguments separated by commas. In the console, the values appear next to each other separated by a space.

We can create variables with the let keyword. Think of a variable like a drawer. Let declares a variable, which means to you that a drawer is created with a handle.

You can put a value in your drawer:

In order to access the value, you have to grab the handle of the box and open it. In this example, you have a drawer called myDrawer. It contains a string written '$1.000' on it. To access your thousand bucks, you have to open the drawer:

You can assign an initial value to your variable with the = sign. This is called initialization, and it can occur either in the same statement where you declared the variable (see x), or after the declaration (see y). You may access a declared variable even if you have not initialized it. Its value becomes undefined.

let x = 5;

let y;
y = x ** 2;

let z;

console.log( x, y, z );

As the above editor is editable, try out one thing.

Move let z below the console.log statement. You should see a ReferenceError:

The message is somewhat misleading, because it means z is not declared using the let keyword. Don't mix this message with the undefined value. You only get the above reference error if you reference a variable that does not exist.

You did the following: you asked for the contents of your drawer z in the console log. But the drawer itself does not exist yet. You only created the drawer afterwards, with let z;:

Side note: I know, in most tutorials, you see var instead of let. This is an advantage of reading an ES2018-compliant tutorial. Don't worry about var for now, you will hear about it later. Ok, I understand. If you do worry about it, read this article.

The Object type

This section will introduce the Object type. We will only learn the basics here.

An object is data structure with String keys and arbitrary values. Imagine it like a machine that accepts a key, and gives you a value. Some people call this data structure associative array, others call it hashmap. These names may sound fancy, but essentially we mean the same damn thing.

Side note: Symbol keys are also allowed for strings. This is an advanced topic, you will learn it later.

A field in an object can be referenced in the following ways:

  • dot notation: object_name.member_name
  • bracket (associative array) notation: object_name[ string_or_symbol_value ]

The delete operator deletes a field from an object.

If a field in an object is deleted or not even declared, the value of this field is undefined.

We will learn a lot more about objects later.


An array is an ordered list of items. The items may be of any type. You know, in most post offices, there are hundreds or thousands of post boxes. Each post box may or may not contain something. Each post box has a numeric handle. Post box 25 may be your box. You unlock it, grab its handle, and access its contents.

The trick is that in case of arrays, you have to imagine the post boxes with keys 0, 1, 2, and so on. Typically, arrays have continuous keys.

Arrays do not have to contain elements of the same type:

Each element of the array can be accessed using an index starting from zero:

In the third example, we indexed out of the array.

Arrays have lengths:

You can add elements to the beginning and to the end of the array.

You can also remove these elements from the array:
- Pop removes the last element from the array and returns it.
- Shift removes the first element from the array and returns it.

Similarly to objects, you can delete any element from the array. The value undefined will be placed in place of this element:

The values of an array can be set by using their indices, and equating them to a new value. You can overwrite existing values, or add new values to the array. The indices of the added values do not have to be continuous:

As with most topics, bear in mind that we are just covering the basics to get you started in writing code. There are multiple layers of knowledge on JavaScript arrays. We will uncover these lessons once they become important.


Think of a function like a mathematical function giving you a relationship between input and output variables. If you don't like maths, think of a function like a vending machine. You give it some coins and a number, and it spits out some cold coke.

This function definition describes the relationship between its input variables a and b, and the return value of the function.

The return statement returns the value of the function. When calling the add function with arguments a and b, it computes the value a+b and returns it. Example:

function add( a, b ) {
return a + b;

add( 5, 2 )

Try to modify the input variables. The return value also changes. Try to call the add function with one variable, e.g. add( 5 ), and see what happens.

Functions are useful to create reusable chunks of code that you can call with different arguments. We will write more useful functions once you learn the basics of control structures.

You can also define functions without placing the name between the function keyword and the argument list. This structure is great if you want create a reference to it using a variable. Remember, the variable subtract is a handle to a drawer. This time, your drawer contains a function.

There is another popular notation first introduced in ES6: the fat arrow notation.

The fat arrow describes the relationship between the argument list and the return value. If there is only one input argument, you may omit the parentheses around it:

All functions can be called using their references:

When a function does not return anything, its return value becomes undefined:

Variables inside the function are not the same as variables outside the function:

The a variable inside the function is valid inside the scope of the function. It shadows the variable a outside the function. Therefore, adding one to the internal a variable does not have any effect on the external value.

The typeof operator

Congratulations! You now know the basic types of JavaScript. This is a perfect time to introduce an operator that returns the type of a value.

The typeof operator accepts one operand and returns a string. This string describes the type of an object.

There is just one problem: arrays, objects, and the null value have the same type. It would be great if we could differentiate between them. Fortunately, ES6 solves the array problem:

Regarding the new value, a simple comparison does the trick:

Functions have the type "function":

Some more operators

We will soon write conditions and loops. In these two control structures, a few operators come handy:

  • +=, -=, *=, /=, %= etc. are abbreviations for adding a value to a variable. a += 1 is the same as writing a = a + 1.
  • ++x increases the value of x by 1, then returns the increased value
  • x++ returns the original value of x, then increases its value by 1
  • --x decreases the value of x by 1, then returns the decreased value
  • x-- returns the original value of x, then decreases its value by 1

I know, the difference between ++x and x++ may not make sense to you right now. I argue that in most cases, it should not even make a difference as long as you want to write readable code.

Both x++ and ++x have a main effect and a side effect. As a main effect, they return a value. Either x, or x + 1, depending on whether you write the ++ after the x or before.

let a = 1;

a *= 2; // a = a * 2;
console.log( '2++: ', a++ );
console.log( '--3: ', --a );

There are two more operators that come handy when formulating boolean conditions.

Suppose you are checking whether a variable is an array and it has a positive length. The and conjuncion is denoted by the && operator:

The value 5 is not an array, so Array.isArray( 5 ) becomes false. A false value in conjunction with anything is false:

Therefore, the second operand of the && operator is not even executed. This is good, because 5.length would have thrown an error. We can rely on the && operator not executing the right hand side expression in case the left side is evaluated as false. This simplification is called a shortcut.

If the left hand side is true, the right hand side is executed. In this case, the value of the and expression becomes the value of the right hand side expression:

We can also define an or relationship between operands. For instance, suppose we have a function that returns true for numbers and strings:

The or operator works as follows: in case of a || b, if a is true, then b is not even evaluated. This is the or shortcut. Once we know that a variable is a number, we don't have to check if the same variable is a string too. We already know that the function should return true.

The value NaN was mentioned.

When formulating a condition that checks if a value is NaN, we have the problem that NaN == NaN is false. The value NaN does not equal to itself. How can we then check if a value is NaN? The answer is, use Number.isNaN().

Control structures

The time has come, when we can fit the puzzle pieces together. You have learned about different primitive and composite types. You know how to check these types. You know the basic functions and arithmetic (addition, subtraction, multiplication etc.) and logical (true or false) operations in JavaScript.

There are only two things missing.

So far, we can write a sequence of instructions that perform a calculation. In software development, there are three types of control structures:

  • sequence: writing instructions one after the other
  • selection: either execute one set of instructions, or another
  • iteration: execute a set of instructions a finite or infinite number of times

As you already know how to sequence instructions one after the other, it is time to learn about selection and iteration. Let's start with selection:

The instructions inside the if-branch are only executed if condition is truthy.

Notice the space between the if and the opening parentheses. This space is there to indicate that if is a keyword and not a function. Although this space is not mandatory, I highly recommend it for readability reasons.

The first value is the console log. The second value is the return value of the printNumber function. Remember, if the return value of a function is not specified, it returns undefined.

If we call the printNumber function with a non-numeric value, it does not print the console log, because the instructions inside the if branch are only executed, whenever the condition inside the if statement is truthy.

It is a bit awkward that we don't print anything in case the input is not a number. You already know everything to write a program that does this. The thought process is the following:

  • if x is a number, print it
  • if x is not a number, print the message "The input has to be a number."

The second biggest problem with this solution is that we are writing too much for no reason.

The main problem with this solution is called lack of abstraction. Imagine that one day somebody comes and realizes that the condition typeof x === 'number' has to be modified. If you forget changing the second condition, you create an inconsistency in your code. We prefer thinking less when we don't have to. Therefore, I recommend another solution, where we only have one condition:

Notice the else keyword. The else branch is only executed if the original condition is not true.

We can cascade this approach further, because after the else, you can have another condition:

The beauty of the above code is that you can read it as if it was plain English. If the state is 1, then log Red. Otherwise if the state is 2, then log Yellow. And so on.

There is an abbreviated version for a long chain of if-else statement: the switch operator. Switch is like a telephone operator. It puts you through some code in case the correct value is stored in your variable. There is also a default line, saying "the number you have dialed is invalid".

function logLampColor( state ) {
switch( state ) {
case 1:
console.log( 'Red' );
case 2:
console.log( 'Yellow' );
case 3:
console.log( 'Green' );
console.log( 'Wrong lamp state' );

logLampColor( 1 );

Try this code example out. Play around with it. Check what happens if you remove the break commands. Check what happens if you call this function with other arguments.

Now that you got a feel for the switch statement, let me explain it. You have a variable inside the switch. This variable may have values. We jump to the case label for which state is equal to the label value.

Then we start executing the code.

If there was no break at the end of the code segment belonging to a label, execution would continue on the next code line. It does not matter that it is now under another label. Code just jumps through the labels.

This is why we have a break statement at the end of each code segment belonging to a label. The break statement jumps out of the closest switch statement, and your program continues execution after the switch statement.

We have two reasons not to include a break statement after a label:

  • we use a return statement instead,
  • we intentionally fall onto the next label (discouraged).


function getLampColor( state ) {
switch( state ) {
case 0:
case 1:
return 'Red';
case 2:
return 'Yellow';
case 3:
return 'Green';

getLampColor( 1 );

In this example, both cases 0 and 1 return 'Red'.

Notice you already know another way to return values without if-else:

The ternary operator gives you red if the state is 1, and green otherwise.

We can place another ternary expression in place of 'Green' to add more lamp states:

Some people don't like this way of writing code. You can hit up their rant about how awful this construct is under the name of ternary operator abuse. I personally do not share their opinion, but this does not matter. If you believe you should use it, use it.

That's all for selection. Let's see iteration. In order to execute the same expressions multiple times, we create loops. A loop is like a cheap song. You know, Berlin is famous for the city of DJs. Sometimes I believe every third man claims he is a DJ. I happened to be a neighbor of one, fortunately, property management terminated his contract. This lunatic guy "worked" on one melody for half a year. And he repeated it over and over and over and over and over and over again.

Think of a loop like the song "Around the world, around the wo-orld. Around the world, around the wo-orld...". You get the idea. Take a melody, repeat it a hundred times, and you get the song. In programming terms, take some code, repeat it x amount of times, and you get code executed a hundred times.

Let's create a function that sums the values of an array:

The first four numbers are not by accident. They were the level selector cheat code of Sonic 2. If you have slight aspergers syndrome, you tend to remember some weird numbers.

let numbers = [19, 65, 9, 17, 4, 1, 2, 6, 1, 9, 9, 2, 1];

function sumArray( values ) {
let sum = 0;
let i = 0;
while ( i < values.length ) { sum += values[i]; i += 1; } console.log( 'The loop was executed ' + i + ' times' ); return sum; } sumArray( numbers );

The variable i keeps track of how many times the loop is executed.

First the JavaScript interpreter examines the condition in the while loop. As i is 0 and numbers.length is 13, we conclude the condition is true.

If the condition is true, we execute the body of the while loop. So we add the ith element of the array to the sum, and increase the loop variable by 1.

Then we compare 1 against the length of the array, 13. As 1 is smaller than 13, we execute the loop body again. The sum variable now stores 19 + 65 = 84. The value of i becomes 2.

We continue this until i becomes 13. Then we realize the condition i < numbers.length becomes false. Once the condition of the while loop becomes false, we continue with the code after the while loop.

This is an important concept, so let's spend a bit more time on the execution. I am using a resource you will find weird: I know, we are learning JavaScript. The author of the website has a great JavaScript engine too, so don't worry, we are not learning Python. The code being executed is valid JavaScript code.

Start moving the slider from left to right to see how the value of the variables change.

The below content may or may not work for you. If you cannot see the example below, please click this link instead.

We have a few more loops to go. The do-while loop executes the loop body at least once, and checks the condition before the end.

Notice the first line in the function. We have to exit the sumArray function before reaching the do-while loop in case the array is empty. Otherwise, the code works in the exact same way as the while loop, except that the condition for running the loop again is at the bottom.

We mainly use do-while loops for input validation. The user inputs a value, then we check its validity.

Let's use the prompt function to get a value.

prompt( 'message' ) opens a dialog displaying message. A textfield appears in the dialog, where you can enter a value. Once you press the OK button, the prompt function returns a string.


This is where the do-while loop makes sense, because we can be sure we need to enter data at least once. In the example summing array members, using the do-while loop is technically possible, but it does not make sense, because the simple while loop is easier.

You will now learn another loop that is perfect for iteration: the for loop. This loop combines several lines of code into one. The execution of the for loop is identical to the while loop:

The for loop has everything you need in one line. You don't have to mix your loop body with the increment of the loop variable. The execution of the for loop is as follows:

  1. initialization_of_loop_variable
  2. check condition. If condition is falsy, exit the for loop
  3. statements in the loop body
  4. increment_loop_variable, then go back to step 2

Rewrite the sumArray function using a for loop. Here is the example with the while loop:

Don't continue reading before you solve this exercise. Please change the while loop into a for loop.

Welcome back!

I hope you liked the exercise. To verify your solution, check this code:

This code should go in place of

Notice you can declare variables in the initializer part of the for loop. The rest of the code works exactly like the while loop.

Let's simplify the for loop a bit further: you can write i++ or ++i in place of i += 1:

In some programming competitions, people tend to count downwards instead of upwards. The reason is that computing values.length costs some nanoseconds more than checking if the value of i is positive:

These wannabe geniuses don't stop there by the way. They go even further:

Weird, isn't it? Instead of iterating from 12 to 0, we iterate from 13 to 1. The condition i is true as long as its value stays non-zero. This is the easiest check a computer can make with an integer.

Suppose i is 13. values[--i] is interpreted as values[12], because first we decrease the value of i, then we equate the expression --i to the new value of i. This is a unique case when writing i-- would have been incorrect, because our array does not even have an element at index 13.

Don't worry if you don't feel like understanding this optimization technique. Once you read this article for the tenth time, you will most likely get it. It's normal. Oh, and by the way, I discourage using such optimizations. Readability always trumps these slight edges. Sometimes you can save seconds in your code, so don't bother with the nanoseconds. It's like being penny-wise and pound-fool.

Another reason to avoid looking smart and optimizing your code is that JavaScript interpreters actually optimize code for you. This is a very easy and straightforward optimization. You don't have to bother doing it yourself. Just stick to this version of the for loop:

Our next simplification is the loop. Why bother iterating an i variable if a loop can take care of it for us?

The loop enumerates all the available indices of the values array from 0 to 12 in ascending order.

I have another simplification for you. What if I said, "why bother using a variable for iteration at all, if we could enumerate the values of the array?". In ES6, there is a loop called the for...of loop, which does exactly that.

That's all. Go back to the editor and substitute the and the for..of constructs in place of your for loop. It works exactly the same way.

We are almost done. Just two small constructs.

We can use break or continue inside the loops:

  • break exits the closest loop it is in, and continues with the next command,
  • continue skips out from the loop body, and jumps back to the condition of the loop.

Example: sum every second element of the numbers array:

This example is artificial, because we could have written i += 2 in a simple for loop to jump to every second value. So we are testing continue just for the sake of the example. Whenever i is even, continue moves execution back to the next iteration of i in values.

Notice that we don't have to use braces around just one statement in the code if it is followed by an if statement or a loop:

is the same as

We still prefer braces, because wrong code formatting may lead to many sources of error. For example, some people might think that statement1 and statement2 belongs to the loop body.


If we added the braces, we would get the following code:

This must be very confusing for people familiar with Python. statement2 is outside the loop.

You already know what a break statement looks like, because we learned it when dealing with the switch statement. It is doing the same thing in loops. Suppose we want to break out from the loop whenever the sum exceeds 100:

I placed the break in braces on purpose to show you that break breaks out of switch statements and loops, not from if statements. When break is executed, control is handed over to the statement after the loop: return sum.

In this specific example, we don't even need a break, because instead of breaking out of the loop, we can return the sum:

Technically, this is an example, where I would suggest a more flexible for loop:


I know, this was a hard nut. You can be proud of yourself, because you covered the same amount of material as me during high school in three 90 minute long classes.

I have created some exercises for you. Now comes the hard part of the learning experience: practice. You cannot just think that you read an article and you know everything. To master a skill, you have to use what you learned. Therefore, I encourage you to sign up below, and start with the exercises I prepared for you.

After you are done with the exercises, I will send you the first six chapters of my book and video course, ES6 in Practice. I chose to include them in this mini course, because these chapters are the most fundamental topics for everyday development.

Because after this tutorial, you will be ready to start learning ES6. If you sign up for free ES6 lessons below, you will get six lessons giving you an in-depth overview on

  • arrow functions,
  • var, let, const (I know, I included a spoiler on this content above),
  • variable number of arguments with ...,
  • the ES6 class syntax,
  • destructuring,
  • the spread operator and rest parameters.

Each lesson gives you some exercises, and you will get access to the reference solutions within a few days.

Besides the ES6 topic, we will also continue this tutorial series with many more useful concepts such as:

  • Embedding JavaScript in HTML,
  • Using the Document Object Model to manipulate HTML content,
  • Event handling,
  • Prototypes and inheritance