DEV Community

Cover image for ⚡️⛓JavaScript Visualized: Scope (Chain)
Lydia Hallie
Lydia Hallie

Posted on • Updated on

⚡️⛓JavaScript Visualized: Scope (Chain)

Time for the scope chain 🕺🏼 In this post I assume you know the basics of execution contexts: I’ll soon write a post on that too though 😃


Let's take a look at the following code:

const name = "Lydia"
const age = 21
const city = "San Francisco"


function getPersonInfo() {
  const name = "Sarah"
  const age = 22

  return `${name} is ${age} and lives in ${city}`
}

console.log(getPersonInfo())
Enter fullscreen mode Exit fullscreen mode

We're invoking the getPersonInfo function, which returns a string containing the values of the name, age and city variables:
Sarah is 22 and lives in San Francisco. But, the getPersonInfo function doesn't contain a variable named city 🤨? How did it know the value of city?

First, memory space is set up for the different contexts. We have the default global context (window in a browser, global in Node), and a local context for the getPersonInfo function which has been invoked. Each context also has a scope chain.

For the getPersonInfo function, the scope chain looks something like this (don't worry, it doesn't have to make sense just yet):

Alt Text

The scope chain is basically a "chain of references" to objects that contain references to values (and other scopes) that are referencable in that execution context. (⛓: "Hey, these are all the values you can reference from within this context".) The scope chain gets created when the execution context is created, meaning it's created at runtime!

However, I won't talk about the activation object or the execution contexts in general in this post, let's just focus on scope! In the following examples, the key/value pairs in the execution contexts represent the references that the scope chain has to the variables.

Alt Text

The scope chain of the global execution context has a reference to 3 variables: name with the value Lydia, age with the value 21, and city with the value San Francisco. In the local context, we have a reference to 2 variables: name with the value Sarah, and age with the value 22.

When we try to access the variables in the getPersonInfo function, the engine first checks the local scope chain.

Alt Text

The local scope chain has a reference to name and age! name has the value of Sarah and age has the value of 22. But now, what happens when it tries to access city?

In order to find the value for city the engine "goes down the scope chain". This basically just means that the engine doesn't give up that easily: it works hard for you to see if it can find a value for the variable city in the outer scope that the local scope has a reference to, the global object in this case.

Alt Text

In the global context, we declared the variable city with the value of San Francisco, thus has a reference to the variable city. Now that we have a value for the variable, the function getPersonInfo can return the string Sarah is 22 and lives in San Francisco 🎉


We can go down the scope chain, but we can't go up the scope chain. (Okay this may be confusing because some people say up instead of down, so I'll just rephrase: You can go to outer scopes, but not to more inner... (innerer..?) scopes. I like to visualize this as a sort of waterfall:

Alt Text

Or even deeper:

Alt Text


Let's take this code as an example.

Alt Text

It's almost the same, however there's one big difference: we only declared city in the getPersonInfo function now, and not in the global scope. We didn't invoke the getPersonInfo function, so no local context is created either. Yet, we try to access the values of name, age and city in the global context.

Alt Text

It throws a ReferenceError! It couldn't find a reference to a variable called city in the global scope, and there were no outer scopes to look for, and it cannot go up the scope chain.

This way, you can use scope as a way to "protect" your variables and re-use variable names.


Besides global and local scopes, there is also a block scope. Variables declared with the let or const keyword are scoped to the nearest curly brackets ({}).

const age = 21

function checkAge() {
  if (age < 21) {
    const message = "You cannot drink!"
    return message
  } else {
    const message = "You can drink!"
    return message
  }
} 
Enter fullscreen mode Exit fullscreen mode

You can visualize the scopes as:

Alt Text

We have a global scope, a function scope, and two block scopes. We were able to declare the variable message twice, since the variables were scoped to the curly brackets.


To quickly recap:

  • You can see "scope chain" as a chain of references to values that we can access in the current context.
  • Scopes also make it possible to re-use variable names that were defined further down the scope chain, since it can only go down the scope chain, not up.

That was it for scope (chains)! There's tons more to say about this so I may add extra info when I have some free time. Feel free to ask questions if you're struggling with anything, I love to help! 💕

Top comments (32)

Collapse
 
evanbacon profile image
Evan Bacon

Hey @theavocoder

Collapse
 
lydiahallie profile image
Lydia Hallie

hi @baconbrix @evanbacon

Collapse
 
lydiahallie profile image
Lydia Hallie

how are you doing sir @baconbrix @evanbacon

Collapse
 
evanbacon profile image
Evan Bacon

Hi the @avocoder me again.

I have a (REALLY (INMPORTANT)) question for you 🤭😊

Thread Thread
 
evanbacon profile image
Evan Bacon

like really imporaant

~ Evan (baconbrix (like and subscribe)) bacon 🥓

Thread Thread
 
lydiahallie profile image
Lydia Hallie • Edited

ask

the

i

m

p

o

r

t

a

n

t

questionee @baconbrix @evanbacon

Thread Thread
 
evanbacon profile image
Evan Bacon

OK

Thread Thread
 
lydiahallie profile image
Lydia Hallie

tik tok im waiting

Thread Thread
 
evanbacon profile image
Evan Bacon

So I was following you on insagtarm 😛 then I think I saw u on medium 🥳🤩 and finally I opened a PR on ur javascript questions 😤

Thread Thread
 
evanbacon profile image
Evan Bacon

my question is u r good at javascript and you also use coffeescript (LMAAO) but why does your descriptioon say you live in florida switzerland and amsterdam?!

Thread Thread
 
lydiahallie profile image
Lydia Hallie

ok so.

so like. first like, i live in like, amsterdam 🍃 then like, like i live in florida 🐬but like, also i like live in like sweden

Thread Thread
 
evanbacon profile image
Evan Bacon

NEAT

Thread Thread
 
evanbacon profile image
Evan Bacon • Edited

ANWAYS , whatss you ## (🤭☎️) because i have , another few question for y o u to answer me to

and wat is ansewr


foo + bar = c

var foo = bar

{
  c++
  // (LOL)
}
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
lydiahallie profile image
Lydia Hallie

discuss

Thread Thread
 
lydiahallie profile image
Lydia Hallie • Edited

isnt this the H.T.M.L. programming code ? ? ?

Collapse
 
rizuwan86 profile image
rizuwan86

thank you

Collapse
 
nickytonline profile image
Nick Taylor

These are all great articles you've created here.

Just FYI, in case you weren't aware, you can link them together using a series so that people can find your past ones as well.

Looking forward to your next article!

Multiple TV and movie characters giving a thumbs up

Collapse
 
adityavardhan profile image
N.Adityavardhan

hi , lydiahallie @theavocoder, i like the way you choose to share knowledge , can you please suggest me how can you do that animations for better understanding, could you please suggest me for how can i do like that animations in windows 8 PC any tools are available for windows or tools or chrome extensions ??

Collapse
 
bigleegeek1 profile image
bigleegeek1

newbie to learning JS. your posts are very clear and informative. your Final JS Notes will be invaluable to others just starting out. look forward to future posts.

bigleegeek

Collapse
 
sudarshan_rayate profile image
Sudarshan Rayate

Hey @lydiahallie

let a = 11;
{
var a = 21;
}
Why this code snippet shows "SyntaxError: Identifier 'a' has already been declared "
and following code run as normal

var a = 11;
{
let a = 21;
}

Collapse
 
krishnagk9964 profile image
KRISHNA K
  • var is function scoped that is it is declared at top of the nearest function scope, global scope in the first one, where already a is present .
  • let is block scoped that is it is scoped inside nearest flower brackets.
  • in second case var a is in global scope and let a is in block scope.
Collapse
 
augustoaraujoo profile image
Augusto Araujo da Rocha

muito bom , ou seja meu escopo que seria minha função declarada com "chaves"
const a = 'hi'
function myFunction() {
// pode ter acesso a todos que estão de fora da minha função
const x = 'ana'
console.log(a) -> 'hi'
}
// mas quem está de fora não consegue acessar os valores de dentro da minha função
// console.log(x) -> undefined

Collapse
 
ericwu91 profile image
EricWu91

Another awesome content! Thanks!

Collapse
 
codermonkey profile image
Shihabudheen US

Great article. I guess you missed to mention, var has function scope.

Collapse
 
realpchauhan profile image
Pradeep Chauhan

Hi @theavocoder how can i learn and strong my fundamental javascript and advance javascript. please share resources.

Collapse
 
evanbacon profile image
Evan Bacon

Does the same methodology apply to telescopes 🔭

Collapse
 
lydiahallie profile image
Lydia Hallie

u need a microscope

Collapse
 
ikemkrueger profile image
Ikem Krueger • Edited

You introduced the "local scope chain", "activation object" and "global object". What has that to do with the "local execution context"?

Collapse
 
tpostolyuk profile image
tpostolyuk

Really useful information!

Collapse
 
chhabraboy profile image
Anurag Chhabra

You're a life saver , that was dope content 🔥🔥

Collapse
 
gabrielduerto profile image
Gabrielduerto

esto es una JOYA, que buena explicación