All About Scopes in JavaScript
So you are new to JavaScript and keep hearing the word “scope” but don’t quite understand what its is and why you should care. I am here to come to your rescue. This is a very important fundamental concept to understand so lets walk through a few examples and explain what it is.
TLDR: Where variables are accessible
Scope
Scope in JavaScript refers to the accessibility of whatever you are referencing is.
Lexical Scope
JavaScript has a lexical (aka static) scope. Sounds fancy right? It just means that children have access to the parent scope (this includes variables, functions, etc.) but parents to not have access to the children scopes.
function example() { let a = 'test' //This has access to a but not b or c function exampleParent() { let b = 'hello' //This has access to a and b but not c function exampleChild(){ let c = 'Children are special' //This has access to a, b, and c } } }
Lexical for JavaScript means at compile time. This means that JavaScript gets its values at compile time rather than other languages that get it dynamically
let animal = 'dog'; function myAnimal() { console.log(animal); } function quack() { let animal = 'duck'; myAnimal(); } function meow() { let animal = 'cat'; myAnimal(); } quack(); // returns dog meow(); // returns dog
If this were run in a dynamic language animal would be different based on the function that was run but since it is lexically scoped (at compile not at runtime) it stays the same. HOWEVER, this is NOT the same as reassigning that variable if you wrote this:
let animal = 'dog'; function myAnimal() { console.log(animal); } function quack() { animal = 'duck'; myAnimal(); } function meow() { animal = 'cat'; myAnimal(); } quack(); // returns duck meow(); // returns cat
you would get what you are expecting as this is reassigning your declared variable not trying to declare the same variable again.
JavaScript has 3 kinds of scope along with its overall lexical scope
Global
Local (or function)
Block
Lets briefly dive into what each of them are
Global Scope
A global scope is anything that is defined outside curly braces. This is usually imports for a file or constants that multiple functions need access to.
const testLog = 'test' //this is global scope function logger(){ const example = 'not global' //this is not global scope it is local/function scope console.log(testlog) //this will work as testLog is globally scoped } console.log(example) //this will not work (will error Uncaught ReferenceError: example is not defined) as example is not globally scoped it is locally scoped and is not in the scope of this console log
Local (or function) Scope
A local also known as function scope anything that is defined within the curly braces of a function. This means that if something is defined inside a function only that function will have access to it. lets use the previous example again
const testLog = 'test' //this is global scope function logger(){ const example = 'not global' //this is not global scope it is local/function scope console.log(testlog) //this will work as testLog is globally scoped console.log(example) //this will work as example is locally scoped and we are still within that scope } console.log(example) //this will not work (will error Uncaught ReferenceError: example is not defined) as example is not globally scoped it is locally scoped and is not in the scope of this console log
Block Scope
Block Scope is something that was added in ES6 with let and const. This means let and const are available in the curly braces they are defined in. This example will show how that works with showing the difference between var, let, and const, but if you want to learn more about that in detail check out this article.
function blockScopeExample(){ const IAmCool = true if(IAmCool){ var dog = 'Dakota'; //local/function scoped const cat = 'Boo'; //block scoped let lizard = 'Lucifer'; //block scoped console.log(1, dog); //'1 Dakota' console.log(2, cat); //'2 Boo' console.log(3, lizard); //'3 Lucifer' } console.log(4, dog); //'5 Dakota' console.log(5, cat); // Uncaught ReferenceError: cat is not defined console.log(6, lizard); // Uncaught ReferenceError: lizard is not defined }
Here we can see when we are within the same curly the block scoped variables were available but as soon as we were out of the curly braces they were not. The function scope was available within the function but not outside of it. to put it all together we have this example
const global = 'i am global' //global scope function blockScopeExample(){ const IAmCool = true if(IAmCool){ var dog = 'Dakota'; //local/function scoped const cat = 'Boo'; //block scoped let lizard = 'Lucifer'; //block scoped console.log(1, dog); //'1 Dakota' console.log(2, cat); //'2 Boo' console.log(3, lizard); //'3 Lucifer' console.log(4, global) //'4 I am global' } console.log(4, dog); //'5 Dakota' console.log(5, cat); // Uncaught ReferenceError: cat is not defined console.log(6, lizard); // Uncaught ReferenceError: lizard is not defined console.log(7, global); //'7 I am global' } console.log(8, dog); //'Uncaught ReferenceError: dog is not defined' console.log(9, cat); // Uncaught ReferenceError: cat is not defined console.log(10, lizard); // Uncaught ReferenceError: lizard is not defined console.log(11, global); //'11 I am global'
Here we can see when we are within the same curly the block scoped variables were available but as soon as we were out of the curly braces they were not. The function scope was available within the function but not outside of it and the globally scoped variable was available everywhere.