Javascript Interview Cheatsheet

Javascript Interview Cheatsheet

ยท

7 min read

In this article, we will discuss some essential topics for your Javascript interview.

Topics covered in this article are :

  • Scope
  • Call Stack
  • Is Javascript Single-threaded?
  • Hoisting

Let's start!

Scope

In normal English, the scope is a limited or restricted region that can be accessed. Only limited things which are in that region can be accessed. The same concept is used in Javascript to check if a variable or function can be accessed or not.

1.png

In the above image, you can see that man 3 can only see the tree in front of him. He cannot see the trees which are in front of man 2 and man 1, so the scope of man 3 is only the tree that is in front of him and so he can only access that tree. Similarly, the scope of man 2 is the tree in front of him as well as the tree in front of man 3, so he can access both these trees but not the one which is in front of man 1. Man 1 can access all the trees as they are in his scope.

The above analogy works in Javascript as well. Let's understand with the below example.

let a = 5;
let b = 6;

function inner1(){
   let sum = a +b;
   console.log(sum);
}

console.log(sum) // Reference error

Here the function inner1 can access the values of a and b and also the value of variable sum. But when the sum is accessed outside the inner1 function it throws an error. This is because sum variable can only be accessed inside the scope of inner1 function.

But then how the inner1 can access the values a and b even if they are not declared inside the function? This happens because of Scope Chaining in Javascript. Before understanding scope chaining let's understand the types of scopes.

Types of Scope

Global scope

Any variable which is not declared inside a function or a block is inside a Global scope. Variables inside the Global scope can be accessed from anywhere.

Local or Function scope

Functions or variables declared inside a function can only be accessed inside that function.

function myPet(){
 let pet = "cat";
 console.log(pet); // Prints cat
}
console.log(pet); // Reference error

Block scope

Block scope is applicable for let and const variables. If declared in a block, these variables can only be accessed inside that block.

{
  let pet = "cat";
  var animal = "lion";
}
console.log(animal); // Prints lion
console.log(pet); // Reference error

Lexical Scope

Lexical scope is like a static scope. It is decided at the time of compilation.

let pet = "cat";

function getMyPet(){
    console.log(pet);
}

function changeMyPet(){
    let pet = "dog";
    getMyPet();  // Prints cat
}

changeMyPet();

The scope for the function is decided at the time of compilation itself. No matter from where this function gets called it will always print "cat" as the scope set for the function does not change depending on the function call.

Scope Chaining

Continuing with our example above let's add one more function inside inner1.

let a = 5;
let b = 6;

function inner1(){
   let sum = a +b;
   console.log(sum);

   function inner2(){
      let c = 50;
      let d = 20;
      console.log(sum);
   }
   console.log(c);  // Reference error
}

When a variable is used in Javascript, it tries to find the value of that variable in the current scope. Like in the case of console.log(sum) the variable sum was available in the current scope so it printed its value. But if the variable is not in the current scope, the Javascript engine tries to look for the value in the outer scope and continues to do so until it reaches the global scope. In case of console.log(sum) inside inner2 it could not find the value of sum in the current scope of inner2, so it finds the value in the outer scope which is inner1, and prints the value.

scope chaining.png Scope chaining works only outwards and not inwards, which means that outer functions cannot access the inner function's scope.

scope chaining 2.png

Call Stack

Javascript engine has Call Stack and Memory heap. So what is Call Stack?

Call Stack is a mechanism used by Javascript to keep track of what function is currently executing and which further function can be executed from within that function. In this, the real stack data structure is used in which functions get added when in the execution stage and are removed once their execution is completed.

When a function is called from the script it gets added to the call stack. If another function is called from inside that function it gets added on top of the current function. This stacking of functions goes on until there is no function call left. Once the function is executed it is popped out from the stack and execution continues from where it was left.

Let's understand it by an example.

function ask(){
     console.log("How are you guys?");
}
function sayHello(){
     console.log("Hello guys!!!!");
     ask();
     console.log("Ok");
}

function sayGoodBye(){
   console.log("Goodbye guys!!!");
}

sayHello();
sayGoodBye();

When the code loads into memory, Global Execution Context is pushed onto the stack.

empty stack.png

Once the execution reaches sayHello(), that function gets called and the execution context of sayHello() gets pushed onto the stack.

stack1.png

Inside sayHello() the execution goes to printing "Hello guys!!!", once it's printed the ask() is called. So the execution context of ask() onto the stack and execution goes to the ask() function.

stack2.png Execution goes into ask() function and prints "How are you guys?" on the console. As the function execution of ask() is completed it is popped out of the stack and the execution continues where it was left in sayHello() function.

stack3.png Function execution of sayHello() continues and prints "Ok" to console. Now the execution of sayHello() is also completed, so it gets popped out of the stack.

Execution moves to the next line and the function sayGoodBye() is called, and hence it gets pushed onto the stack.

stack4.png

sayGoodBye() prints "Goodbye guys!!!" onto the console and as the execution is completed it is popped out of the stack.

When the execution of whole script is completed the Global Execution Context is also removed from the stack and the stack is empty.

When the stack reaches the maximum limit of size , the "StackOverflow" error is received.

function sayHello(){
    console.log("Hello");
    sayHello();
}
sayHello();

In the above code when the function sayHello() it gets added to the call stack. But inside it again the same function is getting called so it adds one more stack frame on top of it. This goes on continuing until it reaches the maximum size of the stack and it throws "StackOverflow" error.

stack5.png

Is Javascript Single-threaded?

Now that we have understood Call Stack in Javascript, we can say that yes Javascript is single-threaded.

Execution in Javascript takes line by line. Taking the above code again as an example, the Javascript engine waits till the execution of function sayHello() is completed and then proceeds to execute sayGoodBye().

As now we know the mechanism of Call Stack, we can understand that until the execution context of sayGoodBye is not popped out from the stack further execution cannot proceed and hence Javascript is single-threaded.

Hoisting

Javascript Hoisting allows us to use the variables and functions even before they are declared in the code. It is a process of moving all the declarations at the top of the scope before code execution.

Let's understand with an example.

console.log(first);
var first = "Hello";
console.log(first);

printHello();

function print(){
   console.log("Function executed")
}
Output

undefined
Hello
Function executed

Hoisting takes place during the memory allocation phase.

Variable Hoisting

As you can observe in the above example when the variable first was used before its declaration it has undefined value. This is because of Hoisting.

In variable hoisting Javascript only hoists declarations, not initialization! This means that until the code execution reaches the actual declaration of a variable inside the code the value of variable is stored as undefined. This only works for variables declared with the keyword var. This does not work in case of let and const.

So Javascript scans the entire code and assigns "undefined" to variables declared with var during the memory allocation phase. When the code execution reaches to the actual declaration of the variable, the value is assigned to the variable. Hence when the variable is used before its declaration it has undefined as its value and after the declaration, the value assigned is used.

Function Hoisting

In the above code example even when using the function print() before it is declared it executes the function and prints "Function executed". In function hoisting, the entire function body is stored in the memory and hence we are able to invoke the function before the actual declaration.

These were some important topics for your Javascript Interview Preparation.

Hope you liked this article. Happy Coding !!! ๐Ÿง‘โ€๐Ÿ’ป

ย