Javascript Interview Preparation CheetSheet

Javascript Interview Preparation CheetSheet

Javascript Interview Topics - Scope and Scope Chain

The most frequently asked questions in Javascript Interviews are basically from some core topics of Javascript, which are Call Stack, Scope Chain, Multi-Paradigm, Single Thread , Hoisting, Prototype-based Object Oriented and 'this' -keyword.

Let's discuss Scope and Scope Chain in Javascript today.

So, We know that each execution context has a variable environment, a scope chain and a 'this' keyword.

Scoping controls how our program's variables are organized and accessed by the JavaScript engine.

It basically wants to know where the variables live or where we can access a variable and where not

in JavaScript, we have something called lexical scoping and lexical scoping means that the way variables are organized and accessed is entirely controlled by the placement of functions and blocks in the programs code. For example, a function that is written inside another function has access to the variables of the parent function.

Scope is the space or environment in which a certain variable is declared and in the case of functions, that's essentially the variable environment which is stored in the functions execution context.

Now, what's the difference between a Scope and a variable environment?

The answer is that for the case of functions, it's the same.

In the Scope of a variable is basically the entire region of our code, where a certain variable can be accessed. Scope is not the same as Scope of a variable.

There are 3 different types of Scope in Javascript.

  1. Global Scope
  2. Function Scope
  3. Block Scope
const name = "suman";
const age = 32;
const year = 1990;

The global scope is once more for top level code. So this is for variables that are declared outside of any function or block. These variables will be accessible everywhere in our program, in all functions and all blocks. So, Everywhere.

function calcAge (birthYear) {
const now = 2022;
const age = 2022 - birthYear;
return age;
}

console.log(now); // ReferenceError

Next, Each and every function creates Scope and the variables declared inside that function scope are only accessible inside that function. This is also called a local scope, and its opposed to the global scope. So, local variables live in the function and outside of the function, the variables are then not accessible at all. If we try so, we get Reference Error.

So function declarations, function expressions and arrow functions all create their own scope.

if ( year >= 1981 && year <= 1996) {
const millennials =  true;
}

console.log (millennials); //ReferenceError

In ES6, blocks also creates scopes. And with Blocks we mean everything that is between curly braces. such as the block of an if statement or a for loop etc.

So just like with functions, variables declared inside a block are only accessible inside that block and not outside of it. Now, the big difference is that block scopes only apply to variables declared with let or const. only let and const variables are restricted to the block in which they were created. That's why we say that let and const variables are block scoped. So if I declare a variable using var in this block, then that variable would actually still be accessible outside of the block and would be scoped to the current function or to the global scope. So we say that var is function scoped.

Now let's understand the Scope of a real-world coding example. Note that here we consider only variable declaration.

Compilation (5).png

We start with the global scope. myName = "suman". the myName variable is the only variable declaration that we have in the global scope. Technically the first function also counts as a variable that is present in the global scope, but for the sake of simplicity, we consider only variable declaration and not functions. Just to keep in mind here variables also work the same for functions.

Inside the global scope, we have a scope for the first function because each function creates its own scope. In the first function age variable that's declared at the top of the function.

Now inside the first scope, let's consider the second function(we will discuss if block in after function scope), which will also create its own scope containing the job variable set to the student. Now here in the second function, we have the console.log code where we need the myName variable and the age variable, which were both not declared inside the current scope.

So How can we access these variables, otherwise we can't create the string in console.log.

The secret is that every scope always has access to all the variables from all its outer scopes. So from all its parent scopes. In our example, this means that the second scope can access the age variable from the scope of the first function.

This also means that the first scope can access variables that are in the global scope, because that is the parent scope. As a consequence of this, the second scope will then also be able to access the myName variable from the global scope, because it has access to the variables from the first scope and this also applies to function arguments.

This is actually how the Scope Chain works!!

In a nutshell, if one scope needs to use a certain variable, but cannot find it in the current scope, it will look up in the scope chain and see if it can find a variable in one of the parent scopes. If it can, it will then use that variable and if it can't, then there will be an error. And this process is called variable lookup.

"An extremely important to note is that this does not work the other way around. A certain scope will never, ever have access to the variables of an inner scope."

In this example, the first scope will never get access to the job variable that is stored in the second scope.

We still have one more scope left here, and that's the one created by this block here. these scopes only work for the ES6 variable types. So for let and const variables. That's why the only variable that's in the scope is the decade variable. The millennial variable isn't declared with const or let and therefore it is not scoped to this block. Instead, the millennial variable is actually part of the first function scope. So again, for a variable declared with var, block scopes don't apply at all. They are functions scoped, not block scoped. Let and const, on the other hand, are in-fact blocks scoped.

It's important to understand that in our example if blocks scope does not get access to any variables from the second function scope and the same, the other way around. it's because of lexical scoping.

The way that we can access variables depends on where the scope is placed, so where it is written in the code. In this case, none of these two scopes is written inside of one another. They're both child scopes of the first function. We could even say that they are a sibling scopes and so by the rules of lexical scoping, they cannot have access to each others variables, simply because one is not written inside the other one. We can also say that the scope chain only works upwards, not sideways.