Pre-bootcamp Learner Notes

Once you’ve followed the Pre-course Introduction section, follow through these self-guided exercises. This will ensure that you’ve got a grounding in the fundamentals of the JavaScript language and Git, so that you’re ready for Bootcamp.

1. Your first JavaScript program

Reading material

Read through the first section (“Introduction”) of The JavaScript Guide to gain some background knowledge about JavaScript in general. Stop before the section called “Getting started with JavaScript”, as during this course you will write and run pieces of code differently to the method described there. Don’t worry about meeting any of the prerequisites mentioned in that guide – you will be able to follow this course even without any prior knowledge.

Exercise 1.1

As we progress through this module, we’re going to build a (very simple!) Calculator application. It will be a console (command line) application – entirely text based. Here’s how to get started:

  • Create a directory that you will keep your Calculator application in. Call it something sensible, like “Calculator”.

  • Open up a command prompt and navigate to your calculator directory (e.g. cd C:\Work\Training\Calculator)

  • Run npm init to create a new Node.js project. Use the default answer to every question it asks you (just press “Enter”) – don’t worry if you don’t understand what all the questions mean!

    • If it doesn’t do anything after the final question “Is this ok?”, double-check there’s a file in the folder called package.json. If it’s there, everything went smoothly and you can exit the npm init process by typing in the console Ctrl + C.
  • In VS Code, open your new directory via File > Open folder…

  • Create a file where you will write your code via File > New file. Call the file “index.js” – this is the conventional name to give to the entry point of a JavaScript program.

  • Write the following code in “index.js”

    console.log('Welcome to the calculator!');
    
  • Run the program: in the command prompt from earlier, still in the directory for your application, run node index.js.

  • Check that the output is what you expect it to be. Have a go at changing the message that is displayed, and re-run the program to see if it worked.

Exercise 1.2

Having done that, we want to put it on GitHub for all the world to see. Or at least, so your tutor can take a look in due course. Here’s how:

  • Go to GitHub
  • Click “New repository”
  • Enter a suitable name for your repository – “Calculator” would do! Make sure the “Owner” is set to your name. Enter a description if you like too.
  • It would be handy to “Add .gitignore” – enter “Node” in the text box.
    • .gitignore is a file describing the types of files that shouldn’t be stored in git – for example, temporary files or anything else that shouldn’t be shared with other team members. You pick a Node-specific one so it’s preconfigured with all the files node and npm will create that shouldn’t be stored in Git).
  • Leave everything else at the defaults. In particular you want a “Public” project, unless you want to pay for the privilege.
  • Click “Create repository”.

That gives you a (nearly) empty repository. Now you want to link that up to your Calculator. Open up a command prompt / PowerShell console / your command line utility of choice and navigate to where your Calculator lives (e.g. cd C:\Exercises\Calculator). Then run the following commands:

git init
git remote add origin https://github.com/YourName/Calculator.git
git fetch
git checkout master

Replace “YourName” in the above with your GitHub username. You can find the correct text to use by clicking “Clone or download” in your project on GitHub and then finding the “Clone with HTTPS” URL.

Info

We’ll discuss these git commands later in the Bootcamp, and for now you don’t need to worry about what they do exactly. Broadly what we’re doing is setting up a local repository that’s linked to the one on GitHub so changes you make can be uploaded there.

If you’re using a GitHub account you created in 2020 or earlier, you may need to replace main with master above because that used to be the default branch name. If you’ve just signed up for GitHub now that won’t be an issue.

You should find that there are no errors, and that the .gitignore file that you asked GitHub to create now exists locally. However if you refresh your web browser on your GitHub project you’ll see that hasn’t changed – the Calculator code is only on your local machine. You can fix this by running this in your command prompt:

git add .
git status
git commit -m "My first piece of JavaScript code"
git push

Now refresh your GitHub browser window and hey presto! Your source code is visible.

When you’re prompted to submit your answers to this exercise, you can just supply the GitHub link – something like https://github.com/YourName/Calculator. Your trainer can see the code, and provide feedback on it if appropriate. Hopefully there won’t be too much to say about this first piece of code, so once you’re done you can move on to the next exercise.

Some notes on git

For the time being, you don’t need to worry too much about what the various commands above actually did. However, here are some details to satisfy your curiosity:

  • git init. Turn the current directory into a Git repository on your local machine. A hidden directory .git is created to manage all the Git internals – the rest of your files stay unchanged.
  • git remote add origin git@github.com:YourName/Calculator.git. Git is a distributed version control system. Your local machine contains a complete and working Git repository, but other people can also have a complete and working copy of the Git repository. If one of those “other people” is GitHub, that provides a convenient way of sharing code between multiple people. This line just says that GitHub (specifically, your Calculator repository) should have a remote copy, and we’re naming that copy “origin”. The name “origin” is just a Git convention meaning “the main copy” – but actually you could use any name, and Git doesn’t really do anything special to make one copy “more important” than another.
  • git fetch. This downloads all the latest changes from GitHub. In this case, that means downloading the .gitignore file to your machine. But it’s not visible on your local machine yet…
  • git checkout main. This tells Git which version of the code you want to see. The “main” branch is the main copy of the code that’s currently being worked on. You’ll notice “Branch: main” is displayed in GitHub too – you can create multiple branches to track progress on different features under development, and this is useful if several people are working on your code at once.
  • git add .. This tells Git to record the changes made to all the files at .. That’s just the current working directory – you could equally well specify each individual file by name.
  • git status. This doesn’t actually do anything, but displays the current status of your repository – you should see some files listed as being changed and ready for commit.
  • git commit -m "My first piece of JavaScript code". This tells Git to save those changes in its history. That way you can go back to this version of the code later, should you need to. Git provides a history of everything that’s happened. The -m precedes a message which explains the purpose of the change.
  • git push. This sends all the changes stored in your local repository up to GitHub. It’s just like the earlier git fetch, but in the opposite direction.

If you want to see the history of your commits, click on the “commits” label in GitHub, or run git log locally. There’s also a local graphical view by running gitk.

2. Data Types and Variables

This topic introduces data types, variables and assignment. We’ll make some small extensions to your Calculator project.

Reading material

Read through the sections “Grammar and types” of the JavaScript Guide. Then read the “Assignment”, “Comparisons” and “Arithmetic operators” section of “Expressions and Operators”. After reading these sections, you should have learned:

  • How to declare a variable
  • The difference between varlet and const
  • How to assign a value to a variable
  • The difference between numbers and strings in JavaScript
  • How to perform common operations on numbers and strings in JavaScript

Exercise 2.1

Add the following functionality to your Calculator project:

  • Prompt the user to enter one number
  • Prompt the user to enter a second number
  • Multiply the two numbers together and print out the result

You should be able to do most of this using information contained in the guide. However you’ll need a way to prompt the user for some input. Node.js doesn’t provide a way to do this easily, but we can install a library called readline-sync that provides this functionality to our project.

  • Open a command prompt and navigate to your project directory.
  • run npm install --save readline-sync
  • At the top of index.js, add the following line of code:
const readline = require('readline-sync');

This downloads the library to your project directory, and tells Node.js that you want to load this library in your application so that you can use its functionality. It also writes some metadata to files called package.json and package-lock.json so that people (like your trainer) who download your application from GitHub will get the same version of the library as you.

Now you can get input from the user in the following fashion:

console.log('Please enter some input:');
const response = readline.prompt();

Note that readline.prompt() returns the response as a string, so you’ll need to make sure to convert the responses to numbers before multiplying them together!

Once you’ve got your program working, commit the changes to GitHub. You should be able to follow the same steps as last time (from git add onward):

git add .
git commit -m "Added a simple multiplier"
git push

3. Branching

This topic introduces branching and conditional logic, via the if and switch statements. We also understand a bit more about the syntax of JavaScript.

Reading material

Read the subsections called if...else and switch in the section “Control flow and error handling” of the JavaScript Guide. You can stop before getting to the section on exception handling – we’ll cover that later on in the course.

These two statements will allow you to write code that behaves differently depending on certain conditions. You may also want to review the “Assignment” and “Comparison” sections of “Expressions and operators”. After reading these sections, you should know:

  • How to write code which uses the if and else statements
  • How to write code using the switch statement
  • The difference between x = y and x == y

Exercise 3.1

Let’s enhance your Calculator a little further. We want to support more operations than just multiplication. We’ll do this by prompting the user to enter an operator before they enter the numbers. So a typical program run might look like this:

Welcome to the calculator!
==========================
Please enter the operator: +
Please enter the first number: 10
Please enter the second number: 4
The answer is: 14

To keep things simple, we’ll just use four operators:

  • + – addition
  • - – subtraction
  • * – multiplication
  • / – division

You can do this exercise with either if...else statements or a switch statement. Why not try both, with a separate git commit after each one so that you and your trainer can review both solutions?

Make sure you git push when you’re done so you can submit the results to GitHub.

4. For Loops and Arrays

This topic introduces for loops and arrays. We’ll obviously add some more functionality to the calculator app too!

Reading material

Read the “Indexed collections” section of the JavaScript Guide. You can stop before reading about “Typed Arrays”.

Then read the “Loops and iteration” section. You can skip over the while and the do...while loops for now, but we’ll come back to them in the next lesson.

After reading these materials, you should know:

  • How to create an array
  • How to set the values in an array
  • How to access elements from arrays
  • How to write code that will run repeatedly inside a for loop.

Exercise 4.1

So far our calculator only performs operations on two numbers. Let’s enhance it so it can do calculations on any number of numbers! For example:

3 + 4 + 5 = 12 1 * 2 * 3 = 6 12 / 2 / 2 = 3

Let’s keep things simple by using the same operator each time. So a typical output might look like this (for the first sum above):

Welcome to the calculator!
==========================
Please enter the operator: +
How many numbers do you want to +? 3
Please enter number 1: 3
Please enter number 2: 4
Please enter number 3: 5
The answer is: 12

You may find you need two for–loops – one to read the numbers and put them into an array, and a second one to go through and add them all up.

5. Functions and While Loops

This topic introduces the syntax for creating and calling functions, the basic building blocks of reusable (and understandable!) code. We’ll also look at the while loop, and add some of our understanding to the calculator tool we’ve been building.

Reading material

Read the “Functions” section of the JavaScript Guide. You don’t need to read the section about “Arrow functions”, but you may find it interesting to do so if you are already familiar with the ordinary function syntax in JavaScript.

Also read about while and do...while loops in the “Loops and iteration” section.

These materials will teach you about:

  • How to define your own functions
  • How to call functions you have defined
  • How to return values from functions
  • How to use function parameters and arguments
  • How to write code that will run repeatedly inside a while or do...while loop.

Exercise 5.1

One of our goals as programmers should be to write “clean code” – that is, code that is simple and understandable. Take a look at this piece of code:

printWelcomeMessage();
performOneCalculation();

It’s hopefully fairly obvious what this code is trying to do, even if you don’t know the details of how those functions work.  *Refactor your code so it looks the same as this example * – that will involve splitting your existing code into two new functions, and then having your program just call them both in turn.

Refactoring

Refactoring is the process of improving your code without changing its behaviour. Those improvements might be to make it more readable, to make it easier to change and extend in future, or something else entirely.

Exercise 5.2

Now take it a step further. I’m guessing you have at least a couple of pieces of code of the form:

console.log('Please enter a number:');
const response = readline.prompt();
const number = +response;

*Create a function that encapsulates this pattern *, and use it to replace all the code that’s similar to the above. The same function should be usable every time you want to print out a message, and interpret the response as a number.

Now see how many further improvements you can make to the readability of your code by splitting it off into smaller, well named functions.

Exercise 5.3

Having done all that, it should be relatively easy to add in a couple of new features, using while loops:

  • Make your calculator keep running – once it’s calculated an answer, it should just loop round and start again. Presumably you don’t want to keep printing the welcome message every time though (So that you don’t get stuck running your program forever, you should know that you can force it to stop by pressing Ctrl + C in the console while it is running).
  • Force the user to enter valid numbers – when prompting for a number, it’s annoying if your program stops working correctly if the user types in a string instead. Have it just ask again in this case.

For the second bullet you might find the isNaN() function useful. You can read about it here, and use it like this:

const maybeNumber = +"42";
if (isNaN(maybeNumber)) {
  // It didn't work -- we have NaN.
} else {
  // It worked -- we have a number.
}

Once you’ve got all that working, push it to GitHub before you move on.

6. Strings and Objects

This topic looks in more detail at strings in JavaScript, and a new data type which is extremely important in JavaScript – objects.

Reading material

Read the sections “Text formatting” and “Working with objects” of the [JavaScript Guide]. After reading these sections, you should know about:

  • Template literals and string interpolation – e.g. `Template with ${expression}`
  • How to create objects using object initializers or constructors
  • How to access and set properties of an object

Exercise 6.1

Review how your calculator deals with outputting strings at the moment. Can you use string interpolation to improve your code? Perhaps try adding some more informative text now that it’s easier to print out more complex messages.

Exercise 6.2

We’d like to enhance the calculator by adding a calculation mode for working with strings. Specifically, we’ll add support for counting the number of times each vowel appears in a given string. Working with strings doesn’t really fit into the current interface, so we’ll modify our main program loop to look something like this:

const ARITHMETIC_MODE = '1';
const VOWEL_COUNTING_MODE = '2';

printWelcomeMessage();
while (true) {
  const calculationMode = getCalculationMode();
  if (calculationMode === ARITHMETIC_MODE) {
    performOneArithmeticCalculation();
  } else if (calculationMode === VOWEL_COUNTING_MODE) {
    performOneVowelCountingCalculation();
  }
}

And the output might look something like this:

Welcome to the calculator!
==========================
Which calculator mode do you want?
 1) Arithmetic
 2) Vowel counting
> 2

Please enter a string: 
> ThE QuIcK BrOwN FoX JuMpS OvEr ThE LaZy DoG

The vowel counts are:
  A: 1
  E: 3
  I: 1
  O: 4
  U: 2

Which calculator mode do you want?
 1) Arithmetic
 2) Vowel counting
>

Implement some functionality along these lines – pay attention to how the example treats uppercase and lowercase vowels the same. Since we’ve just learned about objects, you should use an object to hold the answer when doing the vowel counting calculation.

7. Modules

This topic examines how to divide your code into separate modules. Be warned that the syntax in this topic is specific to Node.js. While there does exist a JavaScript standard for modules known as “ES6 Modules”, most environments for running JavaScript code such as web browsers and Node.js do not yet support this syntax.

The concept of modules, however, is an important principle for keeping your code clean and readable, regardless of the syntax that is used.

The concept of modules

In JavaScript, a module is just a chunk of code. A module is usually just a single .js file containing the sort of things you have already met in this course – objects, functions, constants…

All but the most trivial JavaScript applications will consist of multiple modules. This has some important benefits:

  • Maintainability: A good module will be very self-contained. This means that a well-designed module will have a narrow focus – it will concentrate on doing one thing, and do it well. You should try to write your modules in such a way that if you need to make changes to how one module does something, the other modules are not affected.

  • Readability: Splitting your code into small modules makes it easier for other people to understand what is happening in your code. This is especially true if each module has a well-defined purpose.

  • Reusability: If you have a module that can do a particular job very well, then whenever you want to do that job again in a different place, you don’t need to write any more code to do it – you can just include your module that already does it.

Modules in Node.js

In Node.js modules, you can export functions and objects so that they can be used elsewhere in your application by adding a property to the object referenced by exports. Suppose we have a file circle.js with the following contents:

const PI = Math.PI;

exports.area = function(radius) {
    return PI * radius * radius;
}

exports.circumference = function(radius) {
    return 2 * PI * radius;
}

This exports a function called area and a function called circumference. You would be able to use these functions in another part of your application like this:

// `./circle` means to look in the current directory for `circle.js`
const circle = require('./circle');

console.log(circle.area(1));
console.log(circle.circumference(1));

We didn’t add any property to exports corresponding to the PI constant, so that can’t be used outside of circle.js.

ES6 Modules

After completing this topic, you may be interested to read about ES6 modules. Even though support for them is, at the moment, almost non-existent, it is intended that the ES6 syntax will become more widely adopted over time.

Exercise 7.1

Your Calculator application is getting quite large. Hopefully you’ve split it up into reasonably small and self-describing functions, but that’s still a lot of code to lump together into a single file. Let’s split it up a bit.

A sensible structure for your Calculator program would be the following:

  • index.js, which contains the main program loop and works out whether you want arithmetic mode or vowel-counting mode.
  • A separate module that deals with getting input from the user, with a name like userInput.js.
  • A module that deals with arithmetic calculations. Perhaps arithmetic.js.
  • A module that deals with vowel counting. Perhaps vowelCounting.js.

Try separating your application into modules like this.

Here are some additional questions to answer as you go:

  • What challenges do you face? – what do you find that’s not satisfactory or straightforward? How do you overcome these challenges?
  • How many of your functions need to be exported? – don’t export any functions that won’t be needed outside of the module they are defined in.

8. Further Arrays

This topic discusses arrays in further depth – in particular, the Array object and its methods.

Reading material

Re-read the “Arrays” section of “Indexed collections” in the JavaScript Guide. Pay special attention to the part called “Array methods”, and in particular, the slicemapfilter and reduce methods.

After reading this section, you should have:

  • Reminded yourself how to create, modify and access arrays
  • Learnt how to use slice to get a sub-array from an array
  • Learnt how to use map to apply a function to each element of an array
  • Learnt how to use filter to select particular elements from an array
  • Learnt how to use reduce to combine the elements of an array into a single result

This page will serve as a useful reference to arrays and Array methods throughout this topic, and beyond.

Exercise 8.1

You should already have some code that takes an array of numbers and performs calculations on them (e.g. adds them all up). Modify this code to use reduce instead of a for loop.

Additionally, when performing a division calculation, you should not divide by any numbers that are zero. Don’t do anything special – just skip them in the calculation. The filter method will be useful for this.

9. JavaScript Exceptions

This topic explores error handling and exceptions in JavaScript.

Reading material

In JavaScript, it is possible for some pieces of code to throw what are known as exceptions. When this happens, unless the exception is caught and handled properly, the entire program will stop running at that point.

Exceptions are thrown in JavaScript using the throw keyword. Try adding the following line to your calculator app, just above the main program loop, and then running it:

throw 'This is an error';

The program will immediately stop with a description of the exception that was thrown.

Read the section about “Exception handling statements” in “Control flow and error handling” of the JavaScript Guide. After reading it, you should know:

  • How to throw your own exceptions
  • How to use an Error object
  • How to catch exceptions using try...catch
  • How to define some code that runs whether or not an exception was caught using finally

Exercise 9.1

Make sure to do a separate git commit after each part of this exercise – both parts are instructive and your trainer will want to see each of them separately.

If the user selects an invalid operation (something other than +-* or /) then your application could behave unexpectedly.

Depending on how you’ve written this part of your application, an unexpected operation here might lead to a surprising result! Rewrite this part of code to throw an exception if the operation is invalid.

Make sure that you also include a try...catch block in the calling code so that your program doesn’t terminate completely. You should instead print out an informative message and then continue processing. Try to make the exception message as helpful as possible.

Exercise 9.2

It is good practice to try to recover from errors, if possible, rather than to always throw exceptions. Normally, a function should only throw an exception if there is no way for it to do what the caller asked it to do. For example:

function surnameOfBeatlesMember(firstName) {
    if (firstName === 'John') {
        return 'Lennon';
    } else if (firstName === 'Paul') {
        return 'McCartney';
    } else if (firstName === 'George') {
        return 'Harrison';
    } else if (firstName === 'Ringo') {
        return 'Starr';
    } else {
        throw new Error(`${firstName} is not a Beatle.`);
    }
}

In this case, if the caller passes in a name other than one of the four Beatles, the function cannot return a sensible result, so it instead throws an exception. If the calling code knows that it will always pass in a valid Beatle, then it does not need to worry about catching this exception, but if there’s a chance it might pass in something else, it should wrap any calls to this function in a try...catch block and handle the exception if it arises.

Exercise 9.3

In our application, we don’t need to handle any exceptions if we make sure that the operator we pass in to our calculation function is always valid. Rewrite the code which gets the operator from the user so that it keeps asking them for an operator if they supply an invalid one. This will be similar to the way in which you repeatedly ask the user for a number if they don’t supply a valid number.

While you’re at it, try to modify your code so that an informative message is printed out in each of the following three scenarios, before prompting for more input:

  • The user enters an invalid mode
  • The user enters an invalid operation
  • The user enters an invalid number

Now you know that your operator will always be valid, so you no longer need a try...catch block. Feel free to remove it.

10. Conclusion

Reading material

By now, you will have picked up a solid foundation in JavaScript programming. Re-read any sections of the JavaScript Guide that didn’t make perfect sense the first time round and see if you understand them any better now.

You may also find some sections of the JavaScript Reference interesting reading now that you know some more JavaScript. How about reading the sections on StringNumberArray and Object to learn about these JavaScript objects more in-depth?

Exercise 9.1

In the last lesson, you tried to make your application robust against errors. How carefully have you reviewed and tested your code to make sure it will work in every case? Can you find any scenarios that will cause unexpected behvaiour?

If you find any, can you fix them all up?

Exercise 9.2

Have a think about how you could improve your calculator. How much more functionality can you add? Can you implement some more interesting operators, like exponentiation? Can you add some more calculations with strings?

Is there anything missing that you’d really want to add before you could use this calculator instead of the one that comes with your operating system?

Further reading

There’s plenty more material in the JavaScript Guide to look at now that you’ve finished the rest of the course. Pick the bits that look most interesting!

Beyond that, the best way to learn is:

  • See how much more of what you learn you can shoehorn into your Calculator application.

  • You’ve got a job. Presumably it involves programming. If you didn’t know JavaScript at all before taking this course, you probably haven’t actually done much programming yet… Now is your opportunity! You should know enough to be able to read and understand some simple JavaScript code, even if you still struggle to make modifications to a large application. Ask around for some suitable code to read. Perhaps try to find a known bug or requested feature, and have a go at making suitable changes to the code. If you’re not yet confident enough to do this “for real”, there’s no harm in trying it “for practice” – just don’t commit the code to your source control and your tentative changes will never go live. This is a great opportunity not just to practice JavaScript, but to get familiar with the particular applications you’re going to be working with. After you’ve been on the Bootcamp, you will hopefully be ready to take the next steps and start making a more substantial contribution to the projects you’re working on.

Good luck, and see you at the Bootcamp!