Manage scope

Hey ,

I'm thrilled to help you learn JavaScript. Unfortunately, you've landed on a page where you cannot access with your current purchase.

Please upgrade (use this link) access this content.

I'm super eager to help you learn more!

Manage scope

“Scope” is a name given to an environment that contains variables. If you can access a variable, we say the variable is within scope. If you cannot access a variable, we say the variable is not in scope.

There are five kinds of scopes in JavaScript:

  1. Global scope
  2. Function scope
  3. Block scope
  4. Lexical scope
  5. Closure scope

In this lesson, you’ll learn the first four kinds of scope. We’ll cover closures in a later module.

Global scope

You create a variable in the global scope if you declare the variable outside all functions and curly braces ({}). These variables are called global variables.

const globalVariable = 'some value'

Global variables can be used everywhere in your code. They can be used in any functions.

const hello = 'Hello world!'

function sayHello () {
  console.log(hello)
}

console.log(hello) // 'Hello world!'
sayHello() // 'Hello world!'

If you hear the term local scope, it means the variable is not in a global scope. Local scope can mean function scope, block scope, or even lexical scope.

Function scope

If you create a variable in function, the variable is in a function scope.

function someFunction () {
  const functionVariable = 'some value'
}

You can use a function-scoped variable anywhere inside the function.

function someFunction () {
  const functionVariable = 'some value'
  console.log(functionVariable) // This will log 'some value'
}

someFunction()

But you cannot use the variable outside the function.

function someFunction () {
  const functionVariable = 'some value'
  console.log(functionVariable) // This will log 'some value'
}

console.log(functionVariable) // ReferenceError: functionVariable is not defined

Block scope

A block is a set of code contain within curly braces ({}). If you create a variable inside curly braces, that variable is scoped to the block.

Examples of blocks include:

  1. for loops
  2. if statement
  3. A pair of curly brackets
// For loop
for (const item of items) {
  // item is block-scoped
}

// if statement
if (time === '12pm') {
  const chimeCount = 12 // chimeCount is block-scoped
}

// A block
{
  const name = 'Zell' // name is block-scoped
}

Block scope only applies to variables created with const and let. It does not apply to variables created with var.

var is function-scoped

Variables created with var are always scoped to its nearest function. In the example below, you can see that hello ignores the block scope.

{
  var hello = 'Hello world!'
  console.log(hello) // 'Hello world!'
}

console.log(hello) // 'Hello world!'

This is why you should not create variables with var anymore. Always use const or let.

Lexical scope

You can use a variable after you created it. But you cannot use the variable before you created it.

This behavior is called lexical scope.

console.log(laugh) // ReferenceError: can't access lexical declaration `laugh' before initialization
const laugh = 'haha'

Nested scopes

You can have functions in functions. When do this, you create a nested scope.

// Global scope
const outerFunction = _ => {
  // outerFunction scope
  const innerFunction = _ => {
    // innerFunction scope
  }
}
  • Variables created in the global scope can be used in both outerFunction and innerFunction
  • Variables created in outerFunction can be used in innerFunction, but not in the global scope
  • Variables created in innerFunction can only be used in inner function

It’s easy to visualize scopes with a one-way glass—you can see the outside, but people from the outside cannot see you.

Scopes in functions behave like a one-way-glass. You can see the outside, but people outside can't see you

If you have scopes within scopes, visualize multiple layers of one-way glass.

Multiple layers of functions mean multiple layers of one-way glass

Same-name variables in different scopes

You can use variables with the same name if they exist in different scopes. If this happens, JavaScript uses the variable closest to the current scope.

const sayName = name => {
  console.log(name)
}

const name = 'Zell'
sayName('Vincy') // Vincy

Scopes are not transferable

Each function you create has their own scope. Variables declared in one function cannot be transferred to another function.

In the example below, two does not have access to varOne, even though two called one.

function one () {
  const varOne = `I'm part of one`
}

function two () {
  one()
  console.log(varOne) // Error, varOne is not defined
}

Managing scopes

Here are three rules for managing scopes:

First: Avoid having too many global variables. If you have too many global variables, you may get a variable-name collision (where two variables use the same name).

If variables are declared with let or const, you’ll get an error. If variables are declared with var, the second variable overwrites the first variable (which generates hard-to-find bugs).

Second: Keep variables scoped to the function they need.


// Don't do this
const prize = 'playstation'
function announceWinner(name) {
  console.log(name + ' won a ' + prize)
}
// Do this
function announceWinner(name) {
  const prize = 'playstation'
  console.log(name + ' won a ' + prize)
}

Third: Don’t be afraid to hoist variables to a higher scope if needed.

Let’s say you have this:

function sayName (name) {
  console.log(name)
}

function shoutName (name) {
  console.log(name + '!')
}

sayName('Zell') // Zell
shoutName('Zell') // Zell!

Normally, you’d want to keep name variable within each of these functions. But sometimes, you will want to hoist name to a higher scope.

const name = 'Zell'

function sayName () {
  console.log(name)
}

function shoutName () {
  console.log(name + '!')
}

sayName() // Zell!
shoutName() // Zell!

This one is hard to explain with simple examples. You’ll see why I create this rule when you create dots for the carousel later (next module).

Ordering your code

Here’s a simple order I follow:

  1. Variables required by multiple functions
  2. Functions
  3. Code for execution