Javascript interview preparation cheat sheet

Javascript interview preparation cheat sheet

Scope, Hoist, Single-Thread, Call stack

Table of contents

No heading

No headings in the article.

Hey Geeks,

Here, I am going to discuss the most important topics of javascript that every single javascript developer should know. I know somewhere during journey of learning javascript we all face difficulties to understand these topics. But mastering these topic makes drastic change in writing and understanding the complete flow.

Let's get started.

First topic that we will cover in depth is:

1. What is Scope? The scope in javascript defines the accessibility or visibility of variables or any piece of code. It can be refer as the current context of execution in which values and expression can be used.

  • Why it is so important? Firstly, it provides security against to unintended modifications to the variable from other parts of the program by just allowing it accessibility from certain area.

Secondly, It prevents from namespaces collisions.That is, we can use the same variable names in different scopes.

Types of scopes: There are three types of scope in JavaScript — 1) Global Scope, 2) Function Scope, and, 3) Block Scope.

Scope.png

1. Global Scopes: So, the value or expression that has not been declared under any braces, functions or any block that variable is inside a global scope which can be access from anywhere.

var ineuron = 'Hello Aliens';
function f_ineuron() {
  console.log(ineuron);
}
// Prints 'Hello Aliens'
f_ineuron();

Here, ineuron is inside global scope and f_ineuron function can easilyy access this variable.

2.Local scope or function scope

Each and every function creates its own scope. And the variables declared inside that function are only accessible inside that function and any of its nested functions. This is also called Local Scope.

var message = 'Hi';

function say() {
    var message = 'Hello';
    console.log(message);
}

say();
console.log(message);

Output:

Hello
Hi

When the JavaScript engine executes the say() function, it creates a function execution context. The variable message declared inside the say() function is bound to the function execution context of the function, not the global execution context.

For more clarity, please read the concept of execution context and refer this fig below:

e_contect.png Fig:2

that's why console.log(message) gives output "Hi" as it is bound to global context and the message variable inside say function bound to functiom executive context.

3. Block Scope ES6 introduced let and const variables, unlike var variables, they can be scoped to the nearest pair of curly braces. That means, they can’t be accessed from outside that pair of curly braces. For example:

While let and const are block scoped, the variables defined with var have their scope limited to the current function scope or the global scope. Suppose we declare a variable using var, that variable is accessible outside the block. So, the variable declared using var within a code block is not block scoped; It is function scoped.

{
  let greeting = 'Hello World!';
  var lang = 'English';
  console.log(greeting); // Prints 'Hello World!'
}
// Prints 'English'
console.log(lang);
// Uncaught ReferenceError: greeting is not defined
console.log(greeting);

And a variable created inside an if statement or for loop can only be accessed within that code block. Same as function scope, it is not accessible outside of the block scope.

We can see that var variables can be used outside the block, that is, var variables are not block scoped.

There's another scope available but before diging into it that we should have lil knowledge of schope chain. So, you might have refer Fig 2 above where executive context explained. Please refer it back to understand more about scope chain.

What is 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.

For example:

var y = 20;

function bar() {
    var y = 200;

    function baz() {  
        console.log(y);
    }

    baz();
}

bar();

//Output:

200

In this example:

First, the JavaScript engine finds the variable y in the scope of the baz() function. It cannot find any. So it goes out of this scope. Then, the JavaScript engine finds the variable y in the bar() function. It can find the variable y in the scope of the bar() function so it stops searching.

Here's more elaborate explaination:

scope_chain.png

So, come back to lexical Scope

Lexical Scope: Lexical scope also known as static scoping is a convention used with many modern programming languages. It is the ability for a function scope to access variables from its parent scope.

In simple words, javascript looks for variables in a way , if it can't find a variable in a local Execution context ,it will look for it in a calling context .And if it didn't find it in its calling context. Repeatedly, until it's looking in the global Execution context and if it doesn't find in it will return undefined.

So lexical scoping means that the scope is defined at the location where the variable is defined and not where they run.

Javascript is single-threaded?

Javascript is a single threaded language that means it executes one statement at time.As expected, it executes code in order and must finish executing a piece code before moving onto the next. It has one call stack (First in First Out) and a memory heap which makes it > Synchronous in nature. But it has major two drawbacks - like if a function takes awhile to execute or has to wait on something, it freezes everything up in the meanwhile and It leads to wastage of time and resources.

Q: What does single-threaded mean?

A: That there will be only one thread (process) available for the instructions to be executed.

  • Q: Ok, is Javascript single-threaded?*

A: Yes, Javascript “runtime” is single-threaded. It executes the javascript program. It maintains a single stack where the instructions are pushed to control the order of execution and popped to get executed. And a heap space where the object references are stored and garbage collected.

Let’s look at this simple program and see how it is gets executed.

let myUserOne = () => {
  let userName = "Kriti Sharma";
  const showDetails = () => {
    console.log(`My user name is ${userName}`);
  };
  showDetails();
};
myDetail();

The call stack look like:

g-61lo0Iw.avif

The call stack job is to > push and > pop an instruction as it gets executed.

  • 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.

P.s: wait for more detailed explaination on this. Coming soon

Hoisting:

Hoisting is a process of enabling us to access the variables and functions even before they are initialised.

This is because the JavaScript interpreter splits the declaration and assignment of functions and variables: it "hoists" your declarations to the top of their containing scope before execution.

Javascript only hosts declarations not the initializations.

Here, in below code snippet you will be surprised that this code doesnt raise any error like reference error.even though foo gets assigned after we console.log it!

console.log(greeting); var greeting= 'Hi';

//output: undefined

This is the only reason that we can use greeting variable before its initialization.

Variable Hoisting:

Variable hoisting means that the javascript engines moves all the variable declarations to the top of script . As we have seen in Fig 2 that var variables firstly assign as undefined during scanning process.

Variable hoisting acts differently depending on how the variable is declared. Let's begin by understanding the behavior for var variables.

Variable hoisting with var

When the interpreter hoists a variable declared with var, it initializes its value to undefined. The first line of code below will output undefined:

console.log(name); // undefined

var name = 'barbie';

console.log(name); // "barbie"

But it may generate error if we try to use the variable which is never have been declared in the program like:

console.log(foo); // Uncaught ReferenceError: foo is not defined

This unusual behaviour of javascript using var may leads to errors as we are using it before declaring the variable. But this case is not same with let and const variable.

Variable hoisting with let and const:

Variables declared with let and const are hoisted but not initialized with a default value. Accessing a let or const variable before it's declared will result in a ReferenceError:

console.log(name); // Uncaught ReferenceError: Cannot access 'foo' before initialization

let name = 'bar';  // Same behavior for variables declared with const

This is because let and const has a block scope that we have covered in above section and because of Temporal Dead Zone (TDZ).

Conclusion:

Thanks for reading, and I hope this post helped you learn about hoisting in JavaScript. Feel free to reach out to me on Linkedin if you want to connect or have any questions!