javascript interview preparation cheat sheet

javascript interview preparation cheat sheet

Everything about javascript Main topics

Scope

The scope is the current context of execution in which values and expressions are "visible" or can be referenced. If a variable or expression is not in the current scope, it will not be available for use. Scopes can also be layered in a hierarchy, so that child scopes have access to parent scopes, but not vice versa.

In simple way,

Scope refers to the availability of variables and functions in certain parts of the code.

Types of Scopes in JavaScript

In JavaScript ,there are two types of scope.

  • Global Scope

  • Local Scope

A local scope can be further divided into two types,

Local Scope

  • Function Scope

  • Block Scope

let number=3; //Global Scope
 // Local Scope
function sum(){ //Function Scope 
const arr =[1,2,3];
let sum =0;
for (let i=0; i<arr.length; i++) // Block Scope
sum = sum+arr[i];
}
}

Global Scope

A variable declared at the top of a program or outside of a function is considered a global scope variable. Let's see an example of a global scope variable.

// program to print a text 
let a = "hello";

function greet () {
    console.log(a);
}

greet(); // hello

In the above program, variable a is declared at the top of a program and is a global variable. It means the variable a can be used anywhere in the program.

The value of a global variable can be changed inside a function. For example,

// program to show the change in global variable
let a = "hello";

function greet() {
    a = 3;
}

// before the function call
console.log(a);

//after the function call
greet();
console.log(a); // 3

In the above program, variable a is a global variable. The value of a is hello. Then the variable a is accessed inside a function and the value changes to 3.

Hence, the value of a changes after changing it inside the function.

Note: It is a good practice to avoid using global variables because the value of a global variable can change in different areas in the program. It can introduce unknown results in the program.

Local Scope

A variable can also have a local scope, i.e it can only be accessed within a function.

Example 1: Local Scope Variable
// program showing local scope of a variable
let a = "hello";

function greet() {
    let b = "World"
    console.log(a + b);
}

greet();
console.log(a + b); // error
Output
helloWorld
Uncaught ReferenceError: b is not defined

In the above program, variable a is a global variable and variable b is a local variable. The variable b can be accessed only inside the function greet. Hence, when we try to access variable b outside of the function, an error occurs.

Function Scope

A variable declared inside a function resides in the function scope. The variable can be accessed from functions or blocks inside the function(i.e., nested functions) but not from the outside.

Block Scope

Variables declared inside blocks like for loops or inside curly braces { } with let or const are block-scoped variables.

if(number % 2 === 0) {
  let  even = number;
  console.log("Even", even);
} else {
  let odd = number;
  console.log("Odd", odd);
}
console.log("Even", even); //even is not defined
console.log("Odd", odd); //odd is not defined

The variables even and odd are declared inside { } braces, they are in block scope. In the first diagram, the variable i declared inside the for loop is also a block-scoped.

Lexical scope

Lexical scope is the ability for a function scope to access variables from the parent scope. We call the child function to be lexically bound by that of the parent function. The diagram below outlines the supposed hierarchy that the lexical scope maintains in JavaScript.

Example
var a = 10; // variable a assigned to 10

var func = function (){ // outermost function
    var b = 20;
    console.log("a and b is accessible (outer):", a, b);
    var innerFunc= function (){ // innermost function
        var c = 30;
        console.log("a and b and c is accessible (innner):", a, b, c);
    }
    innerFunc();
    return;
}
func(); // invoke function func 
console.log("only a is accessible (global):", a);

Output

a and b is accessible (outer): 10 20
a and b and c is accessible (innner): 10 20 30
only a is accessible (global): 10

NOTE: JavaScript uses a scope chain to find variables accessible in a certain scope. When a variable is referred to, JavaScript will look for it in the current scope and continue to parent scopes until it reaches the global scope. This chain of traversed scopes is called the scope chain

Scope Chain

The scope chain is how Javascript looks for variables. When looking for variables through the nested scope, the inner scope first looks at its own scope. If the variable is not assigned locally, which is inside the inner function or block scope, then JavaScript will look at the outer scope of said function or block to find the variable. If Javascript could not find the variable in any of the outer scopes on the chain, it will throw a reference error.

Let's take an example and go through this process step by step. Check the below code.

// Global variable
const userName = "Peter";

// Outer function
function calcAge(birthyear) {
  const currentYear = 2021;
  const age = currentYear - birthyear;

   // inner block
  if (age <= 60) {
    var working = true;
    const message = \`Peter is still employed!\`;
    console.log(message);
  }

  // inner function
  function yearsToRetire() {
    const retirement = 60 - age;
    console.log(\`${userName} will be retired in ${retirement} years!\`);
  }

  yearsToRetire();
}

calcAge(1975);

Single Thread

Javascript runs synchronously which means it has only one call stack that is used to execute the program and the block of code is execute one by one. which means that no matter how long the first take takes time to execute it will only proceed to next line only after the first line is executed We can visualize it as a memory stack, one line of code comes, it executes and it gets pops out of the execution context, or a big function comes on it gets executed and then it goes away and so on.

// Executing Synchronously

function makeCoffee(){
console.log("Coffee is made");
)}

function boilEggs(){
console.log("Eggs is made");
}

function toastBread(){
console.log("Bread is toasted");
}

Call Stack

The call stack is used by JavaScript to keep track of multiple function calls. It is like a real stack in data structures where data can be pushed and popped and follows the Last In First Out (LIFO) principle. We use call stack for memorizing which function is running right now. The below example demonstrates the call stack.

function f1() {
  console.log('Hi by f1!');
}

function f2() {
  f1();
  console.log('Hi by f2!');
}

f2();
"Hi by f1!"
"Hi by f2!"

Explanation

The steps and illustrations below explain the call stack of the above function.

Step 1: When the code loads in memory, the global execution context gets pushed in the stack. Step 2: The f2() function gets called, and the execution context of f2() gets pushed into the stack. Step 3: The execution of f2() starts and during its execution, the f1() function gets called inside the f2() function. This causes the execution context of f1() to get pushed in the call stack. Step 4: Now the f1() function starts executing. A new stack frame of the console.log() method will be pushed to the stack. Step 5: When the console.log() method runs, it will print “Hi by f1” and then it will be popped from the stack. The execution context go will back to the function and now there not any line of code that remains in the f1() function, as a result, it will also be popped from the call stack.

Step 6: This will similarly happen with the console.log() method that prints the line “Hi by f2” and then finally the function f2() would finish and would be pushed off the stack.

Hoisting

Hoisting is a very important process in JavaScript that’s made by the interpreter. The interpreter moves the declaration of functions and variables to the top of their scope, prior to the execution of the code. This feature is known as hoisting in JavaScript.

Variable Hoisting

Hoisting works with variables too, so you can use a variable in code before it is declared and/or initialized. However, JavaScript only hoists declarations, not initializations! This means that initialization doesn't happen until the associated line of code is executed, even if the variable was originally initialized then declared, or declared and initialized in the same line. Until that point in the execution is reached the variable has its default initialization (undefined for a variable declared using var, otherwise uninitialized). JavaScript, we can declare variables with const, let, and var. I will explain in detail each variable declaration type individually because the behavior is not the same when hosting.

var hoisting

Here we declare and then initialize the value of a var after using it. The default initialization of the var is undefined.

console.log(num); // Returns 'undefined' from hoisted var declaration (not 6)
var num = 6; // Initialization and declaration.
console.log(num); // Returns 6 after the line with initialization is executed.

Let and Const hoisting

Variables declared with let and const are also hoisted but, unlike var, are not initialized with a default value. An exception will be thrown if a variable declared with let or const is read before it is initialized.

console.log(num); // Throws ReferenceError exception as the variable value is uninitialized
let num = 6; // Initialization

Class hoisting

Classes defined using a class declaration are hoisted, which means that JavaScript has a reference to the class. However the class is not initialized by default, so any code that uses it before the line in which it is initialized is executed will throw a ReferenceError.

Function and Class expression hoisting

The expressions evaluate to a function or class (respectively). They are typically then assigned to a variable or passed to other functions. In this case, the variable declaration is hoisted and the expression is its initialization. Therefore the expressions are not evaluated until the relevant line is executed.