prep

Spaced Repetition

What are we doing now?

You’re going to use this prep time to answer some questions and schedule in times to review your understanding. In your planner or calendar, schedule a short (10 minute) review of your answers:

💡Space at increasing intervals

  • One week from today
  • One month from today
  • Three months from today
  • Six months from today
  • One year from today

Do this now. Then move forward to working through as many of these questions as you can. (You may not complete them all, and that is ok.)

Write down your answers first and then update them after looking at the sample answers, if it’s useful to do so. Use all available tools to help you answer, and remember:

the point is not to complete the exercises the point is for you to secure your own understanding

Examples of tools you might use

Install a UNIX based operating system

Learning Objectives

If you get stuck on any of the below or above instructions, please post in your class channel on Slack.

⚠️CYF does not support Windows!

We have found that we don’t reliably have volunteers at class who can debug Windows problems, and they frequently come up, stopping trainees from making progress.

We do not support Windows so as to not waste lots of trainee and volunteer time. We have made this decision even though Windows is a popular operating system and has features like WSL which help to get experience with Unix.

If you have a Mac or Linux machine already, you already have a UNIX based operating system. All CYF-supplied laptops run Mac OS or Linux. If you have your own machine and it runs Windows you will need to set up a Linux partition.

If you have still not done this you must do it now. If you need help doing this, post in Slack, or bring your laptop to a CYF co-working space to get support. It’s normal to need help with this process. The Ubuntu website has instructions which you can follow to dual-boot your system.

💡Tip

If you are enrolled as a trainee and you don’t have a suitable computer, Code Your Future can lend you a laptop which runs Mac or Linux. You can find information about borrowing laptops on our signposts site.

Install Node with nvm

Learning Objectives

If you get stuck on any of the below or above instructions, please post in your class channel on Slack.

💡tip

Check if you already have NodeJS installed by running node -v in a terminal. The command should return a version number. If it does, you can skip the next steps.

🐧 On Ubuntu

  1. Install nvm by running the following commands in your terminal:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
  1. After the installation is complete, you’ll need to source the nvm script by running:
source ~/.bashrc
  1. Install the latest LTS version of Node.js by running:
nvm install --lts
  1. Check that you have successfully installed Node.js by running:
node -v

You should see a version number like v22.11.0.

  1. Check that you have successfully installed npm by running:
npm -v

You should see a version number like 10.9.0.

 On Mac

  1. Install the the Xcode Command Line Developer Tools by running the following command in your terminal:
xcode-select --install

These may already be installed, in which case you will see “xcode-select: note: Command line tools are already installed.” and can continue to the next step.

  1. Create a (Non-Login Interactive) Shell Configuration File:
touch ~/.zshrc
  1. Install nvm:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
  1. After the installation is complete, you’ll need to source the nvm script by running:
source ~/.zshrc
  1. Install the latest LTS version of Node.js by running:
nvm install --lts
  1. Check that you have successfully installed Node.js by running:
node -v

You should see a version number like v22.11.0.

  1. Check that you have successfully installed npm by running:
npm -v

You should see a version number like 10.9.0.

💡Protip

Using nvm allows you to easily install and manage multiple versions of Node.js on your system. This will help you access projects that use older versions of Node.js.

Interacting with computers

Learning Objectives

Modern computers are complicated: it would be too difficult and time-consuming to list all the components that make up a modern computer. So to build our mental model, we will use this simple definition of a computer:

📖Definition

A computer is a device used to store and perform operations on data.

Using an interface

Learning Objectives

We want to use computers without understanding exactly how they are built. Every day we ask machines to do things, and usually we have no idea how these machines work. We could not use modern technology if we had to understand it completely before we could use it; it would take too long! Instead we use interfaces🧶🧶 interfacesThink of an interface as a gate that allows communication between a user and a machine. The user asks the machine to do things via the interface.

Think about a cash machine (ATM). We go to a hole in the wall with a screen and a keypad. The screen and the keypad are the user interface. We press the buttons and ask the machine to do things - like giving our balance, or withdrawing some money from an account. We don’t need to understand how the information it tells us comes on the screen.

✍️Exercise

Define the user interface for these devices:

  • a calculator
  • a microwave
  • a desktop lamp
  • Facebook
  • Alexa
  • ChatGPT

Terminal interface

Learning Objectives

❗Caution

TODO: Rewrite this to use the VSCode terminal

Programmers need interfaces to ask computers to do things. A computer terminal is an interface where programmers can issue commands to a computer. Because users enter text instructions and receive text output, we say that the terminal is a text-based interface.

Open Your Terminal

Interface via the terminal

We can input a command into the prompt and hit enter. The terminal then passes this command to the computer to execute. Find your own terminal and input the ls command:

ls

The terminal on Mac

terminal
The terminal is a window on the computer, prompting users for instructions.

🖊️ Writing computer instructions

We can issue commands to the computer using the terminal. These commands are instructions that the computer knows how to interpret.

The computer knows ls means “list the files and directories in the current directory”.

During the execution of a computer program, a computer will store and modify data🧶🧶 dataData is information. Text, images, numbers are all forms of data. The data in an executing program is sometimes called the state. A computer program will modify data with operations🧶🧶 operationsOperations modify or create data, from the current data in the program. Adding numbers, joining words, changing text to ALLCAPS, are all operations.

ls is a shell command. Shell is a programming language we use to interact with the files and folders on our computer. You already know at least two more programming languages. Can you name them?

📖Definition: programming language

A programming language is a limited set of rules for writing computer instructions.

Prep dir

Learning Objectives

📂 Create a working directory for the module

  1. Fork the coursework module (always linked in every backlog) and open it in VSCode.
  2. In your VSCode terminal, navigate to the root of your project directory.
  3. Create a new directory called prep to store all the files you’ll be working on for this module.

As you work through the module, you’ll be creating files in this directory to code along with the prep content. You are expected to code along with the prep content.

For simple one liners, use the terminal REPL to run the code. For more complex problems, create files in the prep directory and write the code there. Make commented notes as you go along explaining why you’re doing what you’re doing. Your future self will thank you.

🔑 The most important thing is to secure your understanding

The prep content is designed to help you understand the concepts you’ll be working with in the module. Don’t just read it, code along with it. Also take notes, draw diagrams, pose your own questions and try to answer them.

To really understand programming, you need to write the code yourself, and do the exercises. You must take active part in your learning to succeed.

Running scripts

Learning Objectives

❗Caution

  • Remove references to REPL - we haven’t covered that
  • Combine with next section (logging)

So far we’ve seen how expressions can be evaluated using the Node REPL. The Node REPL is useful for evaluating expressions quickly.

But usually, our programs have many instructions, and we want to keep and re-run them instead of typing them out each time. So we save our instructions in files. Node can also execute instructions written in a file.

We use the node command to run a JavaScript file in the terminal. A JavaScript file ends with .js - this is the “file extension”.

Let’s suppose we have a file age.js. We run the command node age.js. This terminal command is an instruction to execute the program written inside age.js. Our program has five lines. So the computer will read and execute the program one line at a time:

const yearOfBirth = 1990; // declaration
let currentYear = 2023; // declaration

currentYear++; // statement
`I am ${currentYear - yearOfBirth} years old`; // statement

🕹️Activity

Check you can run a file with Node:

  1. In your terminal, create a new file called example.js.
  2. Try writing a few lines in the file.
  3. Get Node to run this file. (Don’t use the REPL now - you should run a command to execute the whole file.)

Once the computer executes these statements, the execution of the program is complete. But we’re left with a problem. With the REPL, when the user inputs an expression statement or declaration, the computer reads and executes the line and immediately prints feedback to the terminal. With a file, the computer will execute each line sequentially until completion without printing the values of each expression it evaluates.

So this new problem can be expressed as a question:

❓ Problem

“How can we check what the values evaluated to in our program during execution?”

Logging

Learning Objectives

❗Caution

Should combine this with scripts section

Printing to the terminal

To look at values when our program runs, we can use a function called console.log.

💡console.log

console usually means a text interface like a terminal. A log is a written record of something that happened.

So console.log will record something that happens in our program and print it to a text based interface.

console.log logs the result of expressions while our program is executing. This is very useful for complex programs when we need to check what values expressions evaluate to at specific moments of our program execution.

Let’s see how to use console.log . In a file called example.js, write the name of the function console.log.

console.log;

If we run this file with Node, we won’t be able to see anything in the terminal. As with Math.round we need to use the syntax for calling a function. Add brackets after the function name:

console.log("hello there!");

We should see the string "hello there!" logged out in the terminal.

Classifying data

Learning Objectives

We’re going to focus on the JavaScript programming language.

A programming language organises data with rules so we understand what we can and cannot do with it. Languages split data up into different categories called data types🧶🧶 data typesA data type is a grouping of data with some particular properties . In JavaScript, we have five data types. We will look first at numbers and strings.

Number data type

10 is an example of the number data type. 3.14 is also part of the number data type; both integers (whole numbers) and non-integers are types of number.

-15 is also part of the number data type. Positive and negative numbers, as well as 0, are all types of number.

String data type

A string is a sequence of characters demarcated by quotes.

"Code Your Future";

🧮 Creating expressions

Think of the numbers 10 and 32. We could ask questions about these numbers, like: What is the sum of 10 and 32?

Another way to say this is what do 10 and 32 add up to? In English we can say this in many ways, but in JavaScript we can say this using numbers and an operator. Just like in mathematics, “the sum of 10 and 32” can be written as 10 + 32:

10 + 32;

In JavaScript, + is an operator🧶🧶 operatorAn operator represents an operation, or act. . It’s a symbol. In this example, + represents the operation “make the sum of the numbers”. It symbolises addition.

The combination of symbols 10 + 32 is an expression🧶🧶 expressionAn expression is a value or any valid combination of values and symbols that results in a single value. We say that expressions evaluate to a single value. So we say that 10 + 32 evaluates to the value 42.

10 is also an expression. It evaluates to the value 10.

"Code Your Future" and "Code Your " + "Future" are also both expressions - both evaluate to the value "Code Your Future".

Saving expressions

Learning Objectives

In programming we often want to reuse our work. Consider the string: "Hello there"

Suppose we want to create different greetings for different people, like: "Hello there, Alicia" "Hello there, Barny"

We can use a variable to store this string and reuse it. How can we create a variable🏷️🏷️ variableA variable is a label for a piece of data. We assign a piece of data to a label and then refer back to this label, in place of the data.

We can create a variable in our program by writing a variable declaration🧶🧶 declarationA declaration is an instruction that binds an identifier to a value. , like this:

const greeting = "Hello there";

Break down the different syntactic elements of this variable declaration:

  • const is a keyword used to indicate we’re creating a variable.
  • greeting is the identifier - it can be used to refer to a variable after it has been declared.
  • = is the assignment operator. It means assign to the label greeting the value of the expression on the right hand side.
  • "Hello there" - this is the expression whose value we’re assigning to the label greeting.

Type this variable declaration into the REPL:

const greeting = "Hello there";

Now refer to the label greeting in the REPL:

`${greeting}, Alicia`

Our greeting variable is stored in memory. We can reuse it to build more expressions:

`${greeting}, Barny`
greeting
Store your string in a variable and reuse it

We just used backticks to create a template literal.

`A template literal places ${expressions} inside strings;

With template literals, we can insert expressions into strings to produce new strings. Any time we want to reference a variable inside a template literal we use a dollar sign $ and a set of curly braces {}. We can put any expression (e.g. a variable name) inside the curly braces. The value that expression evaluates to is then placed inside the string.

When an operation uses an expression, that expression is immediately evaluated, and how it was written is forgotten about. That means that the greetAlicia variable is the same in all three of these cases:

const greetAlicia = "Hello there, Alicia";

📝string literal

In this example, we don’t use a variable or a template to create a string. Instead we write a string "Hello there, Alicia".

A sequence of characters enclosed in quotation marks is called a string literal. "Hello there, Alicia" is a string literal.

Similarly, 10 is a number literal.

const name = "Alicia";
const greetAlicia = `Hello there, ${name}`;
const greeting = "Hello there";
const name = "Alicia";
const greetAlicia = `${greeting}, ${name}`;

The greetAlicia variable doesn’t remember whether you used variables to make it or not - in all three cases, greetAlicia contains the string "Hello there, Alicia". Once a value is made, it doesn’t matter how it was made.

Declarations and statements

Learning Objectives

A variable declaration is an example of a declaration🧶🧶 declarationA declaration is an instruction that binds an identifier to a value . It has the effect of creating a variable.

let versionNumber = "2.0.0"; // declaration
versionNumber = "2.0.1"; // statement

The code above has one variable declaration and one statement.

  1. The first line is a declaration - creating a variable versionNumber with a value of "2.0.0"
  2. The second line is a statement - reassignment🧶🧶 reassignmentReassignment means changing the value associated with an identifier. of the value of versionNumber to "2.0.1"

In this example, we’ve used the let keyword to declare a new variable. The let keyword allows us to create new variables like the const keyword.

However, we can reassign the value of a variable that is declared with the let keyword.

If we’d used const to declare versionNumber, we wouldn’t be allowed to reassign it a new value.

In JavaScript, we build up programs by combining declarations and statements.

Comparing current and target output

Learning Objectives

❗Caution

This block is currently in two places and both need to be updated:

In Onboarding: Rewrite as a general intro to comparing values. Trainees have not covered functions at this point

In Structuring & Testing Data: This would be a useful refresher before we start testing, but needs the context that trainees will already be familiar with teh concept

Let’s start with a function declaration of formatAs12HourClock:

function formatAs12HourClock() {}

Whenever we call formatAs12HourClock we expect it to return a particular value, which we call the 🎯 target output. For example, we expect formatAs12HourClock("08:00") to return "08:00 am". "08:00 am" is the 🎯 target output.

However, the current output is what the function actually returns right now.

👉🏼 Work through the exercises

Let’s start with formatAs12HourClock defined like this:

function formatAs12HourClock() {}

Suppose we now call the function like this:

formatAs12HourClock("05:30");
🤔 When calling formatAs12HourClock(‘05:30’), what is the 🎯 target output?

👉🏼 Keep going

Let’s continue with formatAs12HourClock defined like this:

function formatAs12HourClock() {}

Suppose we call the function like this:

formatAs12HourClock("20:10");
🤔 When calling formatAs12HourClock(‘05:30’), what is the current output?

🧩 Comparing values

We have learned how to log values to the console. We can also compare two values. We check that a function produces some target output with a comparison.

We compare the current output of formatAs12HourClock("08:00") with the target output of "08:00 am" and ask: are these two values the same? We use a comparison operator to compare two expressions and check if they evaluate to the same value. We use the strict equality operator === to check if two values are the same.

Left equals Right

formatAs12HourClock("08:00") === "8:00 am";

=== checks if the values on the left and right of the operator are the same. We can think of formatAs12HourClock("08:00") === "8:00 am" as the question: “Is the return value of formatAs12HourClock("08:00") equal to "8:00 am" ?” This leads to the question:

What will the expression formatAs12HourClock("08:00") === "8:00 am" evaluate to?

✅ ❌ Boolean values

Does 1 equal 0? Yes or No? True or False?

Some values are best represented as strings: any piece of text, a name, address, etc will most likely be stored using the string data type. The number data type can store numbers we use in calculations.

If we’re comparing two things, there are only two different states: true or false. This leads us to the boolean datatype, which only has true or false values. Whenever we compare two values with a comparison operator, we end up with a boolean value: true or false. It’s one or the other. It’s boolean.

// using the strict equality comparison expression

console.log(42 === 10 + 32);
// logs true

console.log(10 * 5 === 60);
// logs false

👉🏾 Now work through the exercises

Look at the code below and predict what each expression will evaluate to. Write your prediction down. Use the Node REPL to check your answers. Check out some relevant documentation if you’ve not seen a particular operator before.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
true === false;
5 == 2 + 4;
4 * 5 == "20";
3 * 2 === 6;
Math.min(3, 4, 5) === 4;
let mhairiName = "Mhairi";
typeof mhairiName === "string";
let mhairiAge = 28;
let isMhairiOldEnoughToDrive = true;
let kilometersMhairiDrivesToWork = 9.4;

👉🏿 Keep Going

Look at the code below and predict what each expression will evaluate to. Write your prediction down. Use the Node REPL to check your answers. Check out some relevant documentation if you’ve not seen a particular operator before

1
2
3
4
5
6
7
"hello Mhairi" === `hello ${mhairiName}`;
"${mhairiName} is 28" === `Mhairi is ${mhairiAge}`;
isMhairiOldEnoughToDrive;
isMhairiOldEnoughToDrive === true;
mhairiAge >= 18;
29 <= mhairiAge;
Math.round(kilometersMhairiDrivesToWork) === 9;

👉🏿 Keep Going

Checking misconceptions 🤔

Look at the code below and then predict what the expression will evaluate to. Be sure to explain your answer too. Use the Node Repl to check your answer. Does the REPL output make sense?

Try using the Node Repl to check your answer. Does the REPL output make sense?

1
console.log(10 + 32) === 42;

Making a choice

Learning Objectives

❗Caution

Useful context for the next block but should be rewritten to be less explicitly dependent on the function

Our function works for morning inputs like "08:00". In this case, the function returns the target output of "08:00 am" as required. However, at the moment, the output of formatAs12HourClock("23:00") is "23:00 am".

💡 We need to execute some different logic when the time is beyond midday

We can interpret this behaviour as a question:

flowchart LR A{Is the time before midday?} -- true --> B[Add am to time string] A -- false --> C[???]

We need to make two changes to our code.

  1. We need to do something different depending on whether the time is before midday. This is called running code conditionally.
  2. And then we need to know what we do if the time is after midday.

We don’t need to solve the whole problem at once. First let’s work out how to do something different depending on the time. We can worry about what we need to do differently once we’ve solved this problem.

💡tip

It’s easier to search for the solutions to smaller parts of problems than the whole problem.

Programming is all about breaking down problems into smaller pieces which we can solve.

Conditionally executing code

Learning Objectives

❗Caution

Examples need to be rewritten without using functions

Recall: JavaScript programs are built up from sequences of declarations and statements.

In programming, we can use an if statement to execute some code when a given condition is true. In JavaScript, we can write an if statement as follows:

main.js
if (condition) {
  // do some code in here
}

The if statement consists of:

  1. if keyword: this is the start of the if statement
  2. condition: condition is an expression that evaluates to true or false. The condition must be in a pair of parentheses: ()
  3. {}: a block statement: any code we want to execute if the condition is true goes inside the curly braces here

We can represent this with a diagram too:

flowchart LR IC{condition} IB[Execute code in body] EXIT([End of if statement]) IC --> |true| IB IC -.-> |false| EXIT IB --> EXIT

🕹️ Playing computer

function checkDivisibility(a, b) {
  if (a % b === 0) {
    return `${a} is divisible by ${b}`;
  }

  return `${a} is not divisible by ${b}`;
}

console.log(checkDivisibility(10, 2));
console.log(checkDivisibility(50, 3));

Play computer with the example above, step through each line in the code and work out happens each time the function is called.

  • What is the return value each time the function is called?
  • What value is assigned to the parameters a and b each time the function is called?

If you’ve not encountered any syntax before, remember to look it up in some documentation.

🎮 Playing computer

function getCountryCode(phoneNumber) {
  if (phoneNumber.startsWith("+44")) {
    return "UK";
  }
}

getCountryCode("+447831620328");
getCountryCode("+989871783972");

Play computer with the example above, step through each line in the code and work out happens each time the function is called.

  • What is the return value each time the function is called?
  • What value is assigned to the phoneNumber parameter each time the function is called?
  • Try describing the purpose of this function - what should it do?

Errors

Learning Objectives

❗Caution

Moving this earlier in the course - check everything still makes sense

🗣️ Recall: A programming language is a set of rules for writing computer instructions.

So we need to understand what happens when we break those rules.

Let’s take an example:

1
2
3
const firstName = "Francesco;
const age = 33;
const nationality = "Italian";

On line 1, we have a variable declaration, but the string has a missing " We’re not obeying the syntactic rules for JavaScript: the rules for writing expressions, statements and other parts of the language.

When we execute the code above, we get this:

const firstName = "Francesco;
                  ^^^^^^^^^^^

Uncaught SyntaxError: Invalid or unexpected token

We get a SyntaxError message. This error message is telling us that we’ve broken the rules of the language.

🕹️Predict, Explain

Each block of code in this activity is broken. Before you run each block of code:

  1. Predict the error.
  2. Explain why the error happened.
const volunteer = "Shadi";
const volunteer = "Abdi";
const volunteer = "Shadi";
volunteer = "Hinde";
console.log(Math.round(10.3);

Saving return values

We can store the return value of a function in a variable. Function calls are also expressions. This means their value can also be stored in variables, just like with operations on numbers or strings.

Suppose we have a file arithmetic.js containing this code:

const result = Math.round(10.3);

When this program is executed, it creates a variable called result and assigns to it the return value of the function, in this case the rounded number.

So result will have a value of 10.

🔭 Logging and returning

Most functions return values we can use in our program.

Math.round takes a single input, does a calculation and then returns a value that we can use when our program is running.

Some functions don’t produce useful return values in our running program; but they can still cause effects.

✍️Predict, Run, Observe

const result = console.log("hello world");
  1. Predict what result will evaluate to when the code above runs.
  2. Execute this line in the Node REPL.
  3. Evaluate the value of the result variable to observe what happens.

When this program runs, the variable result will evaluate to undefined. undefined is a data type in JavaScript which usually means no value has been assigned. Unlike the number data type, which contains many possible values (1, 2, 10.3, etc), the undefined data type has exactly one value, undefined.

This can feel confusing as console.log is a function with a set of instructions. console.log does have an effect: it logs values to the console. However, console.log doesn’t produce an output that we can use inside the rest of our running program.

💡tip

Key fact: console.log is used to print values to the terminal. It doesn’t produce an output in the running program.

Interpreting errors

Learning Objectives

❗Caution

Moving this earlier in the course - will need a new example without using a function

An error is thrown

When we run the file with Node, we get an error in the console:

% node clock-example.js
/Users/dwh/CYF/clock-example.js:12
const currentOutput = formatAs12HourClock("23:00");
      ^

SyntaxError: Identifier 'currentOutput' has already been declared
    at wrapSafe (node:internal/modules/cjs/loader:1383:18)
    at Module._compile (node:internal/modules/cjs/loader:1412:20)
    at Module._extensions..js (node:internal/modules/cjs/loader:1551:10)
    at Module.load (node:internal/modules/cjs/loader:1282:32)
    at Module._load (node:internal/modules/cjs/loader:1098:12)
    at TracingChannel.traceSync (node:diagnostics_channel:315:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:215:24)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:158:5)
    at node:internal/main/run_main_module:30:49

Node.js v22.4.1

When an error is thrown, the program stops and an error report is sent to the user.

As programmers, we will see a lot of errors. It’s useful for us to be able to read them.

Interpreting the output

Each line of output here tells us something useful.

The first line is:

/Users/dwh/CYF/clock-example.js:12

Your output was probably different. But it will have the same parts. Some text, then a colon (:), then a number.

✍️Exercise

  1. Work out what the parts of this line mean.

  2. Why are they different on my computer than yours?

  3. How can we use both pieces of information?

Often, looking at one line of a file is enough to understand what’s wrong. So the message also shows us a copy of the line that caused the problem:

const currentOutput = formatAs12HourClock("23:00");

Then the output tells us the error message:

SyntaxError: Identifier 'currentOutput' has already been declared

We may not know what this means yet, but it’s something we can learn about.

✍️Exercise

Write down three ways you could find out what this means.

Each line starting with “at” is showing us a “Stack trace”. We’ll skip over this for now. In the future we’ll see how it can be useful to us.

Finally, we have this line:

Node.js v22.4.1

✍️Exercise

What does this line mean? Why might it be useful to know this information?

Add your answer to your spaced repetition calendar. Your understanding of this will grow over time. Answer the question again in the future, and compare it to your previous answer.

Interpreting this error

Learning Objectives

❗Caution

Moving this earlier in the course. Update this to use new example from previous page.

We saw this error - let’s try to understand it:

SyntaxError: Identifier 'currentOutput' has already been declared

Knowing what we changed

It can be useful to remember when our code last worked, and what we changed since then.

💡tip

Source control can help here.

If you commit your code every time you make something work, you can use git to easily see what changed since your last commit.

When we just had the first 10 lines of code here, everything worked. When we added the rest, we got this error:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function formatAs12HourClock(time) {
  return `${time} am`;
}

const currentOutput = formatAs12HourClock("08:00");
const targetOutput = "08:00 am";
console.assert(
  currentOutput === targetOutput,
  `current output: ${currentOutput}, target output: ${targetOutput}`
);

const currentOutput = formatAs12HourClock("23:00");
const targetOutput = "11:00 pm";
console.assert(
  currentOutput === targetOutput,
  `current output: ${currentOutput}, target output: ${targetOutput}`
);

💡Tip

Run your code very often.

If we changed one thing since our code last worked, we know what change is the problem. If we have written 100 lines of code since we last saw it work, we have 100 possible problems.

Interpreting the error message

The error message tries to tell us useful information:

SyntaxError: Identifier 'currentOutput' has already been declared

When we get an error, we should make sure we understand all of the words in the error message. If we don’t, we should look them up or ask someone.

✍️Exercise

For each word in this error message, write down what it means.

If you don’t know a word, look it up.

Make sure you understand each word. Make sure you could explain the word to someone without reading the answer to them.

Expand for example definitions - only expand this after you have written yours down. Compare your answers with these.
  • SyntaxError - If we Google “JavaScript SyntaxError”, MDN tells us this is “an error when trying to interpret syntactically invalid code”. So - we wrote some code which isn’t allowed.
  • Identifier - If we Google “JavaScript Identifier”, MDN tells us: this is “a sequence of characters in the code that identifies a variable, function, or property”. On line 12, the identifier is the variable name: currentOutput.
  • currentOutput - This is the variable name we used in our code. This is the identifier that the error is about.
  • has, already, and been are all standard English words with no special meaning.
  • declared - We learnt about this already in this course - a declaration is where we make a new name (e.g. a new variable) in JavaScript.

Reading that back, we can rephrase this error message:

We wrote some code which isn’t allowed. We tried to declare a new variable named currentOutput. But we had already declared something named currentOutput.

Reusing variable names

Learning Objectives

❗Caution

This may not make sense with the updated error example but should still be covered alongside variables. Move this earlier with a different example if necessary.

We saw this error:

SyntaxError: Identifier 'currentOutput' has already been declared

Now that we understand it, let’s fix it.

We’re not allowed to declare a new variable with the same name as an old one. Both lines 5 and 12 here try to declare a new variable named currentOutput:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function formatAs12HourClock(time) {
  return `${time} am`;
}

const currentOutput = formatAs12HourClock("08:00");
const targetOutput = "08:00 am";
console.assert(
  currentOutput === targetOutput,
  `current output: ${currentOutput}, target output: ${targetOutput}`
);

const currentOutput = formatAs12HourClock("23:00");
const targetOutput = "11:00 pm";
console.assert(
  currentOutput === targetOutput,
  `current output: ${currentOutput}, target output: ${targetOutput}`
);

remember

Make sure you understand the error message before you try to fix the code.

If you don’t understand what’s wrong, you probably won’t be able to fix it!

Fixing the error

We want to do multiple assertions. And we’re using variables in our assertions. But we’re not allowed to use the same name twice. The simplest way we can fix this problem is by changing the name of the second variable. Remember to also change where we use the variable, not just where we declare it!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function formatAs12HourClock(time) {
  return `${time} am`;
}

const currentOutput = formatAs12HourClock("08:00");
const targetOutput = "08:00 am";
console.assert(
  currentOutput === targetOutput,
  `current output: ${currentOutput}, target output: ${targetOutput}`
);

const currentOutput2 = formatAs12HourClock("23:00");
const targetOutput = "11:00 pm";
console.assert(
  currentOutput2 === targetOutput,
  `current output: ${currentOutput2}, target output: ${targetOutput}`
);

Trying again

After making this change, let’s try running our code again. We get this output:

% node clock-example.js
/Users/dwh/CYF/clock-example.js:13
const targetOutput = "11:00 pm";
      ^

SyntaxError: Identifier 'targetOutput' has already been declared
    at wrapSafe (node:internal/modules/cjs/loader:1383:18)
    at Module._compile (node:internal/modules/cjs/loader:1412:20)
    at Module._extensions..js (node:internal/modules/cjs/loader:1551:10)
    at Module.load (node:internal/modules/cjs/loader:1282:32)
    at Module._load (node:internal/modules/cjs/loader:1098:12)
    at TracingChannel.traceSync (node:diagnostics_channel:315:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:215:24)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:158:5)
    at node:internal/main/run_main_module:30:49

Node.js v22.4.1

Fortunately, we’ve seen this kind of error before. It’s exactly the same as the last one, but about the targetOutput variable on line 13, instead of the currentOutput variable on line 12.

✍️exercise

Fix this error, and try running your code again.

Now the second assertion fails with the following message:

% node clock-example.js
Assertion failed: current output: 23:00 am, target output: 11:00 pm

We expect this. Our function just adds " am" to the end of the time, which only works for times in the morning. We have proven our code isn’t complete yet. Next we can fix it so that this test passes.

✍️Exercise 1

✏️ Write another assertion that checks formatAs12HourClock returns the target output when passed another time input in the afternoon.

Backlog

Learning Objectives

In software development, we break down complex projects into smaller, manageable parts, which we work on for a week or two. These periods are called “sprints.”

A sprint backlog is like a to-do list. It lists what the team has decided to work on this sprint. It’s chosen from a larger list, usually called the “product backlog,” which holds the entire project to-do list.

In this course, the backlog is a set of work designed to build understanding beyond the concepts introduced in the course prep. For your course, we have prepared a backlog of mandatory work for each sprint. You will copy these tasks into your own backlog. You can also add any other tickets you want to work on to your backlog, and schedule all of the tasks according to your own goals and capacity. Use your planning board to do this.

You will find the backlog in the Backlog view on every sprint.

Copy the tickets you are working on to your own backlog. Organise your tickets on your board and move them to the right column as you work through them. Here’s a flowchart showing the stages a ticket goes through:

flowchart LR Backlog --> Ready Ready --> in_progress in_progress[In Progress] --> in_review in_review[In Review] --> Done

🕹️Backlog (30 minutes)

  1. Find the sprint backlog
  2. Copy your tickets to your own backlog
  3. Organise your tickets on your board