Javascript Scope

In Javascript, Scope is the concept of where something is available. That "something" is either a variable or a function.

The concept of scope is used in everyday tools such as Slack, Discord, and Teams. Let's say you get hired as an engineer for a big organization and you get access to the company's Slack feed. The Slack team is organized into channels. Some channels are company-wide, like the main #general channel, and some are used by teams inside of the company for fast communication like #engineering, #marketing, #sales, etc. Each of these channels forms their own scope, so their messages are only visible to those who have access to the channel. So if you were hired as an engineer, you can interact with other members of your team in the #engineering channel, but you can't view messages posted inside #marketing or #sales because those are different scopes that you don't have access to. So just as every message on Slack is sent in a channel, every piece of Javascript code is run in an execution context.

Different Types of Scope

There are three different types of Scope; Global, Function, and Block scope. Variables and functions declared in the Global scope or global execution context are accessible everywhere in our Javascript code. Lets take look at an example:

const test = 10; // variable w/ global scope

function equation(number) {
  number * test;
}

equation(test) // => 100
  • In our example, the test variable and the equation function are both declared in the global execution context having global scope. This means that the equation function has access to test.

We leave the global context when we declare a new function(Function Scope) and write code in that function body. The function creates a new execution context with its own scope. Lets look at an example:

function myFunc () {
  const myVar = 42;

  return myVar * 2;
}
// => undefined

myFunc();
// => 84
  • Here, inside the function body we can refrence variables and functions declared in the function's scope.
  • But, from outside the function, we can't reference anthing declared inside of it, like so:
function myFunc () {
  const myVar = 42;
}
// => undefined

myVar * 2;
// Uncaught ReferenceError: myVar is not defined

The function body creates its own scope. Like on Slack, it's a separate channel where only the members of that channel can read the messages sent in it.

The last type of scope is the Block scope. An example of a block statement is an if statement. Lets look at an example:

if (true) {
  const myVar = 42;

  let myOtherVar = 9001;
}

myVar;
// Uncaught ReferenceError: myVar is not defined

myOtherVar;
// Uncaught ReferenceError: myOtherVar is not defined

Best Practices

Variable declaration plays a big role in scope, for example using var, let, const, or none at all.

If we got back to our block scope example, using var inside of our block will not work the same as using let or const because variables declared with var are not block-scoped.

if (true) {
  var myVar = 42;
}

myVar;
// => 42

Using var can lead to a lot of bugs so it is best to use let and const.

It's also possible to declare a variable without var, let, and const. Variables created without a var, let, and const keyword are always globally-scoped, regardless of where it is in our code. Lets take a look:

if (true) {
  lastName = 'Lovelace';
}

function bankAccount () {
  secretPassword = 'il0v3pupp135';

  return 'bankAccount() function invoked!';
}

lastName;
// => "Lovelace"

bankAccount();
// => "bankAccount() function invoked!"

secretPassword;
// => "il0v3pupp135

Declaring global variables and functions should be a last resort because the more pieces of code that can access a specific variable, the more places you have o check for bugs. It is best to keep scoped small and specific. Going back to the Slack example, you wouldn't want messages coming from the #engineering channel to be visible in the #sales or #marketing channels.