DEV Community

Cover image for ⛓️Scoping in JavaScript
Ahmed Mahmoud
Ahmed Mahmoud

Posted on

⛓️Scoping in JavaScript

Understanding scope is key for writing organized and effective code. In this blog post, we'll check out how scoping works in JavaScript and how it can help you, So first lets take a look at the difference between free and bound variables…

Free vs. Bound variables

Variables declared outside of functions have global scope and are accessible from anywhere in the code, while variables declared within functions have local scope and are only accessible within that function.

A free variable is a variable that is used within a function, but is not declared within that function nor passed to it as a parameter. It is either declared in the global scope or in an outer function's scope.

A bound variable, on the other hand, is a variable that is declared within a function and is only accessible within that function.

Here's an example to illustrate this:

let x = 10; // Global scope

function foo() {
  console.log(x); // Free variable
}

function bar() {
  let y = 20; // Bound variable
  foo();
}

bar();
Enter fullscreen mode Exit fullscreen mode

In this example, x is a free variable because it is used within the foo function, but it is not declared within the foo function. It is declared in the global scope.

y is a bound variable because it is declared within the bar function and is only accessible within that function.

Another Example:

function fun() {
    let a = "a"
    function innerfun(){
         a = "b" //Free variable
    }
    innerfun();
    console.log(a); //b
}
fun()
Enter fullscreen mode Exit fullscreen mode

variable a is accessible by the inner function though the change reflect on outer

function fun() {
    let a = "a"
    function innerfun(){
        let a = "b" //Bound variable
    }
    innerfun();
    console.log(a); //a
}
Enter fullscreen mode Exit fullscreen mode

this inner variable a only exists within the scope of the inner function, and has no effect on the variable a in the outer function.

Dynamic vs. Static Scoping

Now lets discover the difference between dynamic scoping and static/lexical scoping…

The concept of dynamic and static scoping is determined by the design of the programming language, not by the runtime or execution time.

Static/lexical Scoping

In static scoping (also known as lexical scoping), the scope of a variable is determined at compile time (interpretation time in JavaScript) based on the location of the variable declaration in the code. In other words, the scope of a variable is determined by the blocks of code in which it is defined and can be referenced.

Dynamic Scoping

In dynamic scoping, the scope of a variable is determined at runtime based on the call stack. In other words, the scope of a variable is determined by the sequence of function calls that led to the current point of execution.

For Example:

// Dynamic vs. Static scoping example
function foo() {
  console.log(a);
}

function bar() {
  let a = "b";
  foo();
}

let a = "a";
bar();

// Output in dynamic scoping: "b"
// Output in lexical scoping: "a" <== Output
Enter fullscreen mode Exit fullscreen mode

Also here:

// Dynamic vs. Static scoping example
function foo() {
  console.log(a);
}

function bar() {
    a = "b"; //Reference for a in global scope
  foo();
}

let a = "a";
bar();

// Output in dynamic scoping: "b" 
// Output in lexical scoping: "b" <== Output
Enter fullscreen mode Exit fullscreen mode

In the previous example the Output in the previous example is b that’s because bar function has access to variable a in the global scope as it carries a reference to it in its local scope not because of JavaScript using dynamic scoping.

JavaScript Scoping

JavaScript uses lexical scoping, meaning that the scope of a variable is determined by the location of the variable declaration in the code, not by the runtime environment.

This means that variables in JavaScript are statically scoped and that the scope of a variable is determined at the time the code is written, not at the time it is executed (from within the call-frame / execution context).

But don’t confuse this with the concept of inner function getting the variable value from the outer function for example:

function bar() { //Outer
  let a = "b";
  function foo() { //Inner
      console.log(a);
  }
  foo();
}

let a = "a";
bar();

//Output because of closures: "b"
Enter fullscreen mode Exit fullscreen mode

Although the behavior is similar to dynamic scoping (not the same) due to the existence of closures in JavaScript output in the previous example will be b (I will make a full separate post on closures)

Scopes in JavaScript

there are three main scopes in JS

Global Scope

In JavaScript, global scope is for variables and functions that are accessible everywhere in the code. These variables are declared outside of any function and can be used all over.

Local Scope

Local scope, also known as function scope, is for variables and functions that are only accessible within a certain function. This is handy for creating functions you can use again and again.

Block Scope

Block scope, which was introduced in the ES6 version of JavaScript, is for variables or functions that are only available within a certain block of code, like an if statement or a for loop. This is a great way to keep your variables neat and tidy, to ensure your variables are block scoped always declare them with let and const keywords.

Scoping concepts

those are concepts that are thought to be actual scopes but they are not…

Script Scope

Script scope is not a real scope, but it's a term that's used to refer to the scope of the whole script file. This means that anything declared outside of a function is accessible to the entire script, regardless of which function the code is in, you can think of it as an extension for the global scope that is specific to let and const declared variables.

Lexical Scope / Closure Scope

Lexical scope is not an actual scope, but it's a concept used to refer to the way that JavaScript looks for variables in the code. It looks for variables in the local scope first and, if it can't find them, it looks for them in the global scope. This helps to identify which variables are accessible where and helps to keep code organized.

you can find amazing animated illustrations on Lydia Hallie post about scoop chaining
here is a link to check out her post:

⚡️⛓JavaScript Visualized: Scope (Chain)

Closures

Closures are a concept in JavaScript that involve a function accessing an outer function's variables and functions. Closures allow developers to create private variables that can only be accessed within the function, which is a great way to keep code organized and efficient. Closures are not a scope, but they provide some of the same benefits that scope can provide.

(I will talk more in detail about closures in a full separate post)

Conclusion

To wrap it up, scope is an essential concept in JavaScript and understanding how it works can make your code run more smoothly and stay organized. Whether you're using global, local, or block scope, it's important to keep your variables in order. With a bit of practice and knowledge, you can use scope to your benefit.

Top comments (0)