JavaScript Interview Preparation Cheatsheet

JavaScript Interview Preparation Cheatsheet

What is Scope ?

The scope is the current context of execution in which values and expressions are accessible or can be referenced.

In JavaScript, the following scopes are available:

1. Global Scope - the outermost scope in a javascript file. The variable declared in global scope are accessed by all nested scopes.

let globalVariable = 5;
function nestedFunc() {
  console.log(globalVariable);
}
nestedFunc(); // The output is 5

2. Module Scope - In ES6, modules were introduced. Module is simply a piece of code. Multiple modules are combined to create a larger application. The variables declared inside a module are accessible within that module only.

3. Block Scope - Variables declared using let and const are block scope. In JavaScript, this {} defines the block. The if, for, while create the block scope. In the below example, the variable localVariable is available inside the if block only, outside it, it will throw a reference error.

if (true) {
  let localVariable = 5;
  console.log(localVariable); //output is 5
}
console.log(localVariable); // throws ReferenceError

4. Function Scope - A function defines a scope for variables declared using let, const and var. In the example, the variable local is accessible inside foo() only, outside it, it will throw an error.

function foo() {
  var local = 5;
  console.log(local); //output - 5
}

Note: A variable declared using var is function scope but not block scope.

Lexical Scoping

The inner function can access variables from the outer functions' scope, This is lexical scoping.

let globalVariable = 5;
function nestedFunc() {
  console.log(globalVariable);
  let nestVariable1 = 1;
  function nestedFunc1() {
    console.log(nestVariable1);
    let nestVariable2 = 2;
    function nestedFunc2() {
      console.log(globalVariable, nestVariable1, nestVariable2);
    }
    nestedFunc2();
  }
  nestedFunc1();
}
nestedFunc();

In the above example the nestedFunc2() can access the globalVariable, nestVariable2, nestVariable1 variables declared in it's lexical scope.

Scope chaining - In JavaScript, the required variables are first searched in the local scope, then in its lexical scope and then in its outer lexical scope until it is found else throw a reference error. All the lexical scopes form a chain like structure and this is called scope chaining.

Closure - The closure captures the variables from the lexical scope of the function and make this variables available to that function regardless of where the function is invoked.

function outerFunc() {
    let outerVar = 5;
    function innerFunc() {
        console.log(outerVar);
    }
    return innerFunc;
}

function otherFunc() {
    let storeInnerFunc = outerFunc();
    storeInnerFunc();
}

otherFunc();  // output - 5

In the above example, the outerFunc() returns the innerFunc(). Inside the otherFunc(), outerFunc() is executed and stores the innerFunc() in the variable storeInnerFunc and it is then executed.

The output of the above code is 5. The outerVar variable is accessible by the innerFunc() inside the otherFunc() though it is not available in the lexical scope of the innerFunc(). This is because of closure. The function encloses the variables from the lexical scope.

Is JavaScript a single threaded programming language?

Yes, JavaScript is a single threaded programming language i.e. it has a single call stack. It executes the code in sequence, one line at a time, thus it is synchronous too. Whatever is at the top of the call stack is executed first and after its execution, it is popped out of the stack. No matter how much time consuming the process is, JavaScript waits until that task is completed and then move to the next line.

Call stack

Call stack is a data structure used by the JavaScript engine to keep a track of the code being executed. The JavaScript engine executes the code one line at a time. Whatever task is to be done are stacked together onto the call stack and whatever comes at the top of the call stack is executed first and then popped out of the stack after its execution.

// add the given number and then multiple it

function multiple(num) {
    return num * num;
}

function add(num) {
    let addedNum = num + num;
    return multiple(addedNum);
}

let result = add(2);

console.log(result);

The call stack for the above code snippet is -

image.png

After the console.log(), the call stack will again become empty.

Hoisting

In JavaScript, functions and variables can be used before their declaration, this is called hoisting. Consider the following code snippet -

add(5, 10);

function add(a, b) {
console.log(a + b)
}
// output - 15

Though the add() is declared after its invocation, it won't throw any error because of hoisting.

Hoisting in case of variables - The variable declared using var are hoisted and initialized with undefined.

console.log(a);  // output - undefined
var a = 5;

In case, the variable is declared using let or const, they are still hoisted but not initialized with a default value like in case of var. It will throw a ReferenceError stating that the variable is initialized somewhere but it can't be used before its declaration.

console.log(a);  // output - ReferenceError: Cannot access 'a' before initialization
let a = 5;

The reason for the ReferenceError for the above code is Temporal Dead Zone (TDZ).

Temporal Dead Zone(TDZ) - A let or const variable is said to be in Temporal Dead Zone from the start of the block until the code execution reaches the line where the variable is declared and initialized.