5.1: Program Lifecycle and State

Learning Objectives

By the end of this lesson, you should be able to:

  • Explain the difference between a global and local variable.

  • Understand when and why to use global variables.

  • Declare and use global variables.

  • Briefly explain "function scope".

Introduction

Our programs have so far handled ephemeral (temporary) data that exists only while main or the relevant parent function is running. Now we will handle data that persists across runs of main, and functions in our app in general.

Scope Hierarchy

Variables defined "higher up" the scope hierarchy will be available to reference in "lower" scopes, but not the other way around.

Globally-defined variables can be accessed in function scope and block scope, and anywhere else in the program, hence global. Variables defined in block scope can only be accessed within that block.

Global Scope

Any variables defined outside of a function or a block of code exists in global scope. This include function definitions. So main, and any other functions we have written are in global scope. This allows us to call the function inside other functions or nested blocks of code.

So far, we have been creating variables inside of a function or a block of code, but nothing is stopping us from creating a variable at the "top level" of script.js, in global scope.

Global Variables

We will use our dice game to demonstrate the value of data persistence. In a dice game, we may want to keep track of the "bank roll" or score for the duration of our game. We need a syntax to store a value (bank roll in this case) that we read and update when main runs and is also available the next time main runs.

The syntax we will use is called "global variables". Global variables in SWE Fundamentals will persist from when the program loads in the browser to when we close the tab or reload the page. Try running the following code line by line in Chrome DevTools. The variable number persists across our commands, but when we refresh the page, number is no longer available. Similarly, our global variable data will persist across function calls, but not across browser sessions.

var number = 5;
number = number * 2;
number;

Function Scope

Sensibly, variables declared within the function definition exist in function scope. When your program first loads, the functions are defined, but are not yet executed until a function call is made. You can verify this by opening the console, and checking the value of main.

Understand that the function main that we have been using is defined in the global scope, so the browser knows what it is, but attempting to access any variables defined within the function via the console will result in an error.

Once the function has been executed, the program returns to the scope from when the function was called, and all the variables declared and used by the program within the function are effectively forgotten. Only the return _value_** persists**. This return value, as you have already been doing before, is stored into another variable.

Consider the example below where convertKmToMiles(input) is assigned to myOutputValue (line 6).

var convertKmToMiles = function (input) {
  return input / 1.609;
};

var main = function (input) {
  var myOutputValue = convertKmToMiles(input);
  return myOutputValue;
};

Different functions have their own scope. Variables declared in one function are not accessible in another function. Hence it is possible to re-use variable names in different functions, or more generally, in different scopes. However, you are strongly advised against this.

In contrast to "global variables" then, "local variables" are variables created within a smaller scope within the global scope.

Recall the main function we've been using so far. In this function, myOutputValue only exists during the execution of main, corresponding to 1 Submit-button click.

If we try to inspect the value of myOutputValue in the console after clicking Submit, myOutputValue doesn't exist.

myOutputValue;

This behaviour is common to all variables declared inside a function, and a demonstration of "function scope" in JavaScript. This means that variables declared in a function are available for the life of that function, then they disappear.

Block Scope

Block scoping applies to any variable defined in a block of code within a pair of {}. In SWE Fundamentals, this is mostly blocks of code defined by if-statements.

Similar to Function Scope, once the program exits the block and returns to a higher scope, variables declared within the block are effectively forgotten and inaccessible.

Global State

Building on the logic above, global variables can thus be used as a "global state" of sort.

This is the idea that we can declare variables outside of functions and have those variables persist across function calls, keeping their values intact.

In this example, we persist papayaCount, in this case a count of the number of times a user has clicked Submit. papayaCount is part of myOutputValue, which shows the user how many times they have clicked Submit.

// Variables in the Global Scope - papayaCount and main
var papayaCount = 0;
var main = function (input) {
  // Variables in the Function Scope (of the main function) - myOutputValue
  papayaCount = papayaCount + 1;
  var myOutputValue = 'You have ' + papayaCount + ' papayas';
  return myOutputValue;
};

Global Variables for Dice Guessing

Bank roll or score is an application of the global "counter" variable to our dice game. In the following example, we increment bankRoll every time the player correctly guesses the dice roll.

var bankRoll = 10;

var main = function (input) {
  var randomDiceNumber = rollDice();

  var myOutputValue = 'you lose. current bank roll: ' + bankRoll;

  if (randomDiceNumber == input) {
    bankRoll = bankRoll + 1;

    myOutputValue = 'you win. current bank roll: ' + bankRoll;
  }

  return myOutputValue;
};

Exercises (Base)

Follow Along

Follow along with the videos and duplicate the code.

App Setup

For the following exercises, start with the SWE Fundamentals Starter Code template and replace the code in script.js with the following dice game code.

var rollDice = function () {
  // produces a decimal starting from 0 and ending BEFORE 6 (5.999999...)
  var randomDecimal = Math.random() * 6;

  // take off the decimal -> 0 to 5
  var randomInteger = Math.floor(randomDecimal);

  // it's a number from 0 - 5 ... add 1 -> 1 to 6
  var diceNumber = randomInteger + 1;

  return diceNumber;
};

var main = function (input) {
  var randomDiceNumber = rollDice();

  var myOutputValue = 'you lose';

  if (randomDiceNumber == input) {
    myOutputValue = 'you win';
  }

  return myOutputValue;
};

Last Roll

Create a version of the dice game that tells the user what their previous dice roll was.

Sample Output

Your last roll was 4. You just rolled a 3. You guessed 3. You win!

Win / Loss

As the user continues to play the game, tell them what their current win / loss percentage is.

Sample Output

You win 23.5% of the time. You just rolled a 4. You guessed 3. You lose!

Exercises (More Comfortable)

Most Rolled

Keep track of the number that's rolled the most times.

Sample Output

You just rolled a 4. 2 is the number you roll the most. You guessed 3. You lose!

Guessing

If the player guess is off-by-1 they win 1 point. If the player guess is exact they win 2 points.

Advanced Guessing

The player guess can be off by up to 4. If the player guess is off-by-4 they win 1 point. Off-by-3, 2 points, off-by-2, 3 points, off-by-1, 4 points, exact, 5 points.

Reference Solutions

Click here to view the reference solution. Please only refer to the reference solution after you have attempted the exercise. Note that there are many ways to implement the exercise and the reference solution is only 1 way.

Last updated