JavaScript Interview CheatSheet💻

JavaScript Interview CheatSheet💻

·

7 min read

What is Scope?

The scope is the accessibility of variables, functions, or objects in some particular part of your code during runtime. They came into existence when the principle of least privilege was applied in programming language designs. Scopes provide some level of security to your code, i.e are only used when they are really needed. Scoping parts of your code help improve efficiency, track and reduce bugs. It also solves the naming problem when you have variables with the same name but in different scopes, so reduce namespace collision.

Types of Scopes

  • Global and Local Scope
  • Lexical Scope
  • Block Scope

Global and Local Scope

Any variable declared outside of a function belongs to the global scope and is therefore accessible and can be altered from anywhere in your code. The outermost part of the code comes under the global scope. Variables defined inside a function are in the local scope. They have a different scope for every call of that function. This means that variables having the same name can be used in different functions. This is because those variables are bound to their respective functions, each having different scopes, and are not accessible in other functions.

// global scope
var scope = "global";

function scope1(){
    // local scope 1
    var batch = "FSJS";
    console.log(batch);
}

function scope2(){
    // local scope 2
    var name = "Deepak";
    console.log(name);
    function innerScope(){
        // Inner scope
        var scope = "inner scope";
        console.log(scope);
    }
    innerScope();
}

scope1();
scope2();

Lexical Scope

When a function within another function, the inner function has access to the scope in the outer function, this is called Lexical Scope — also referred to as Static Scope as it may only be called (referenced) from within the block of code in which it is defined.

function fullStack(){
    const skills = ["FrontEnd", "Backend", "Databases"];

    function frontEnd(){
        const tech = ["UI", "JavaScript", "React" ];
        console.log(tech);
        // skills accessible here 
        console.log(skills);
    }
    frontEnd();

    function backend(){
        const tech = ["Node Js", "Express", "Django" ];
        function databases(){
            const db = ["MySql", "MongoDb"];
            console.log(db);
            // tech accessible here
            console.log(tech);
            // skills accessible here
            console.log(skills);
        }
        databases();
    }
    backend();
}
fullStack();

image.png

JavaScript starts at the innermost scope and searches outwards until it finds the variable/object/function it was looking for.

The important thing to remember is that the Lexical scope does not work backwards, which means that vice versa is not true. Functions defined with outer scope have no access to variables of the inner defined function.

Block Scope

Block statements like if and switch conditions or for and while loops and {} unlike functions, don't create a new scope. Variables defined inside of a block statement will remain in the scope they were already in. Speaking clearly, any set of variables defined in a particular scope block made with {...} are accessible only and only inside that block.

if(true){
    let sum = 0; // only accessible within the block
    for(let i=0; i<10; i++)
        sum+=i;

    console.log(sum);
}
console.log(sum) // ReferenceError: sum is not defined

Synchronous JavaScript – How the Call Stack Works

So what happens when you define a function and then invoke it? The JavaScript engine maintains a stack data structure called function execution stack. The purpose of the stack is to track the current function in execution.

  • When the JavaScript engine invokes a function, it adds it to the stack, and the execution starts.
  • If the currently executed function calls another function, the engine adds the second function to the stack and starts executing it.
  • Once it finishes executing the second function, the engine takes it out from the stack.
  • The control goes back to resume the execution of the first function from the point it left it last time.
  • Once the execution of the first function is over, the engine takes it out of the stack.
  • Continues unit the stack is empty.

Let's take an example to understand how the call stack works.

apu79k5A4.avif

Now, the following code contains a function inside a function, so let's visualise it using a call stack diagram. hTx-_QX_5.avif

Now, as the javascript loads the program, the global execution context kicks in and is pushed into the stack.

  • Firstly, hello() is invoked so it is pushed to the top of the call stack.
  • hello(), invokes hi() and hence the hi() local execution context is pushed on the top.
  • As the execution of hi() is finished up, it pops out and javascript now executes the remaining code of hello().
  • As the execution of hello() is finished, it is also popped out of the stack and the execution of the remaining global code starts.
  • Now, the hey() function is invoked and it is pushed to the top of the call stack.
  • As the execution of hey() is finished, it pops out of the stack.
  • Now, the js engine executes the remaining code of the global execution context and then it also pops out and the stack becomes empty.
  • Execution of script completes at this point.

The bottom line is that everything that happens inside the call stack is sequential. This is the Synchronous part of JavaScript. JavaScript's main thread makes sure that it takes care of everything in the stack before it starts looking into anything elsewhere. This sequential format of executing code and focusing only on a single thread at a time makes it a synchronous and single-threaded programming language.

How Hoisting works in JavaScript?

JavaScript hoisting refers to a mechanism in which functions, variables and classes are available throughout the program, even before they are declared. The javascript interpreter appears to move the declaration of functions, variables or classes to the top of their scope, prior to execution of the code.

Hoisting in variables

Hoisting works with variables too, so you can use a variable in code before it is declared and/or initialized.

An important thing to note here is that 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).

Since the ES6, javascript has 3 ways to use variables: var, let and const Let's understand them only by one.

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(framework); // undefined
var framework; // declared and hoisted
framework = "React Js"; //initialised
console.log(framework); // React js on console

The same thing happens if we declare and initialize the variable in the same line.

// If the variable is declared and initialised in the same line,
// then also only the declaration is hoisted.
console.log(framework); // undefined
var framework = "React Js"; // declared, hoisted and initialised
console.log(framework); // React js on console

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

Note that it is the order in which code is executed that matters, not the order in which it is written in the source file. The code will succeed provided the line that initializes the variable is executed before any line that reads it.

Hoisting in Functions

One of the advantages of hoisting is that it lets you use a function before you declare it in your code.

console.log(findSum(2,3,4)); // 9

function findSum(a,b,c){
    return a+b+c;
}

console.log(findSum(1,2,3)); // 6

With function hoisting, it doesn't matter where in the code a function is declared, it can be used the same way anywhere in the program and it works perfectly.

See also, let, var and cosnt

Â