Training Days Project: understanding scope

Hello all,

I have small issue wrapping my head around the concept of scope as applied in code.

In the Training Days Exercise steps 2-4, the instructions are clear and the result is as expected (from following instructions). However, when I try to think as to why the instructed changes produce these [correct] results I get confused.

For example:

Step 2: How does adding an unassigned days variable before the if/else if statement resolve the ReferenceError? Additionally, why use an unassigned days variable?

const getTrainingDays = event => {
	let days;
  if (event === 'Marathon') {
    let days = 50;
  } else if (event === 'Triathlon') {
    let days = 100;
  } else if (event === 'Pentathlon') {
    let days = 200;
  }

  return days;
};

Step 3: Why does deleting the let’s within the if/else if statements resolve the undefined problem?

const getTrainingDays = event => {
	let days;
  if (event === 'Marathon') {
    days = 50;
  } else if (event === 'Triathlon') {
    days = 100;
  } else if (event === 'Pentathlon') {
    days = 200;
  }

  return days;
};

Please let me know if you need any more information?

1 Like

First, lets elaborate on the way you tell the script there is a new variable and how you assign a new value to that variable.

To define a variable you let the script know by calling an identifier (let, const or var) and then assign a value.

// Define a variable example with identifier let
let exampleLet = 5 //I can be reassigned in the future ;)

// Define a variable exampleConst with identifier const.
const exampleConst = 7 // I cannot be reassigned in the future.

The const identifier tells the script that the variable you define cannot be changed. reassigning a variable identified as const will result in an error.

let identifier tells the script that the variable you define can be changed. It is possible to upon definition that the variable has no value.

The var identifier results in a variable that can be reassigned. This was the only identifier before Javascript ES6. But I would personally only use let and const nowadays.

To reassign a variable you will simply have to call the variable by its name and then give it a new value, remember this is not possible with a const:

exampleLet = 6 // reassign the value of variable example 
console.log(exampleLet) // returns 6

exampleConst = 8 // result TypeError: Assignment to constant variable.

Variable can be global so that everywhere in the Javascript this variable is accessible. You do this by defining the variable directly inside the Javascript outside of a function. If you define a function inside a function it will not exist outside of that function. This is called scope.

Now, on to the exercise and your questions ;).

You have a function is expected to return a value of the variable days. days is not needed outside of the function so making it a global variable is unnecessary. Instead you will have to define the variable days inside the function.

Because the value of days depends on the outcome of the if..else if statement you have to make sure you introduce the variable before the statement, and since days should be modifiable the variable has to be of the type let or, if you are old school, var.

Now, why is the following code without assigning a empty variable resulting in a reference error?

const getTrainingDays = event => {

  if (event === 'Marathon') {
    let days = 50;
  } else if (event === 'Triathlon') {
    let days = 100;
  } else if (event === 'Pentathlon') {
    let days = 200;
  }

  return days;
};

The reason why this does not work is simply because the scoping rules for let and const identifiers in the context of statements says that internal defined variables do not exist outside of the statement. Since you define days inside of the statement, return days will result in a reference error. Note: for some weird reason and remnants of the past, this is not the case for var identifiers… @mtf why?

On to the next issue. Defining an empty variable days before the if statement.

const getTrainingDays = event => {
  
  let days;

  if (event === 'Marathon') {
    let days = 50;
  } else if (event === 'Triathlon') {
    let days = 100;
  } else if (event === 'Pentathlon') {
    let days = 200;
  }

  return days;
};

This does solve this reference error because return can now actually return something. However since days is empty an undefined will be returned.

In the last instance you removed the let inside the if statements and it actually works. How so?

const getTrainingDays = event => {
  
  let days;

  if (event === 'Marathon') {
    days = 50;
  } else if (event === 'Triathlon') {
    days = 100;
  } else if (event === 'Pentathlon') {
    days = 200;
  }

  return days;
};

Hey, now we are doing something completely different :wink: . Instead of defining days, you reassign days (remember the bit of theory at the start of my reply?). Thus days is defined empty before the if.. else if statement, it gets reassigned by the if statement and then returned with a new value :smiley: .

I hope I have answered your question in a way that you understand :wink: . Keep on coding!

2 Likes

This answered my question and more! Thank you @janneslohmeijer.

1 Like

You are very welcome!