Skills Based Js Scope

Objectives

  • Explain how scope works in JavaScript
  • Explain what lexical or function-level scope is
  • Explain what block-level scope is
  • Explain how local and global variables work in JS

What Is Scope?

Scope is the current context of your code. Understanding scope is the key to understanding how your variables interact with each other in your code. Without a solid understanding of scope, your variables could be storing entirely different values than you think they are.

The Key To Scope

To determine a variable's scope in JavaScript, ask yourself two questions:

1. Is it declared inside a function?
2. Is it declared with the `var` keyword?

If a variable is declared in the outermost scope of a project, it's going to be global no matter what – that is, whether you write var foo = 'bar' or foo = 'bar'. Remember, saying that a variable is "global" simply means that it can be accessed everywhere.

Think of something else that we could call global — maybe smiling. Everywhere you go, you can smile and people will know what you mean. Similarly, when we have a global variable, everywhere we go in a program, we know what that variable refers to.

Variables declared with var are only available within that function's scope. Variables declared without var attach themselves to the global object.

function myFunction() {
  var y = 2;
  console.log(y);
}

In myFunction function above, the variable y was defined with the var keyword, so it's only available inside the function. If we run myFunction() in console, we'll see 2 printed out. But if we try console.log(y); in console, we'll get an error. If instead, we write and call

function myFunction(){
  y = 2;
  console.log(y);
}

We can call console.log(y) outside the function as well.

Let's take another example:

var x = 1;

function myFunction(){
  y = 2;
  console.log(x);
}

console.log(y); // Error!

console.log(x); // 1

If you copy and paste this into the JS Console, you'll get an error with console.log(y); At this point in time, even though y is a global variable, the variable hasn't been defined. JavaScript has just stored a function called myFunction.

If we were to do this:

var x = 1;

function myFunction(){
  y = 2;
  console.log(x);
}

myFunction(); // 1

console.log(y); // 2

console.log(x); // 1

Now, because of the myFunction call, the global variable y exists, and console.log(y) will work!

The Scope of Scope, or Getting Closure

One of the most powerful things about scope in JavaScript is how easily we can hide variables from the global scope but still make them available in inner scopes.

function outerFunction() {
  var innerVariable = "I'm sort of a secret.";

  return function innerScope() {
    var inaccessible = "Nothing can touch me.";

    return innerVariable;
  }
}

JavaScript has first-class functions, meaning that we can pass them around with ease. When we call outerFunction(), the returned value is another function.

Let's give it a try:

var myScope = outerFunction();

// the stringified version of `innerScope()`
myScope;

Cool! What happens if we try to call innerScope() directly?

innerScope();

This will throw the error undefined is not a function (very helpful, JavaScript). But if we call myScope (the variable to which we assigned the output of outerFunction()):

myScope();

We should see "I'm sort of a secret." returned! What happened?

Inside outerFunction(), we made the variable innerVariable available to innerScope() in what we call a closure. In this example, innerScope() remembers the environment it was created in, and it maintains references to variables declared in that environment in a closure. As we noted above, JavaScript functions have access to their entire outer scope, so the innerScope() function has access to outerFunction()'s environment and to the global (window) environment.

Note, though, that outerFunction() doesn't know anything about what's in innerScope() — the variable inaccessible is aptly named, because we can't get at its value except inside innerScope().

Shadowy Variables

There were some hints about this concept above, but we want to explicitly draw attention to something called "variable shadowing." Take the following example:

var animal = 'dog';

function makeZoo() {
  var animal = 'cat';

  console.log(`I think I'll put this ${animal} in the zoo.`);
}

makeZoo(); // "I think I'll put this cat in the zoo."

animal // "dog"

Notice how even though we have two variables called animal, only the one declared inside the makeZoo function is used within the function, and only the one declared outside of the function is available outside of it.

This is called "shadowing," when the inner variable shadows the outer variable of the same name. While it might seem trivial here, it's easy to imagine how shadowing can cause problems in larger, more complex applications — our variables might have completely unexpected values! We might get dogs when we want cats!

Resources

View JS Scope on Learn.co and start learning to code for free.

Unlock your future in tech
Learn to code.

Learn about Flatiron School's Mission

With a new take on education that falls somewhere between self-taught prodigy and four-year computer science degree, the Flatiron School promises to turn students with little programming experience into developers.

In the six months since the Manhattan coding school was acquired by WeWork, it has spawned locations in Washington, D.C., Brooklyn, and London. Now, WeWork is opening a fourth Flatiron School location, this time in Houston.

Adam Enbar, Flatiron School's cofounder, believes now is the time to grow. "How the world is changing has impacted working and learning in very similar ways. We think education fundamentally is about one thing: enabling people to pursue a better life."

Learn. Love. Code.
Students come to Flatiron School to change their lives. Join our driven community of career-changers and master the skills you need to become a software engineer or a data scientist.
Find Us