JavaScript Interview Preparation Cheatsheet

JavaScript Interview Preparation Cheatsheet

What is Scope in JavaScript?

In programming, the scope is the extent of the visibility of a variable or function. It decides what other pieces of code can see it. If a variable is scoped within a function, only the function can access it. If a variable is scoped globally, it can be accessed everywhere. Scopes can be nested, where one scope can be placed inside another. The scope is a critical concept in programming and understanding it can help you avoid many bugs in your code!

Types of Scopes in JavaScript:

1. Block Scope

2. Function Scope

3. Global Scope

Block Scope in Javascript

Block scope is when a variable or function is scoped to a {} or { }. You’ve probably encountered this in a while loop. You’ll notice that there is a { } block in the while statement. This means the code inside the {} is scoped to the while loop. You cannot access the variables or functions outside the while loop. This is because of block scope. The scoped code is destroyed when the while loop ends. This type of scope is used for controlling the flow of code execution.

A code block in JavaScript defines a scope for variables declared using let and const.

if (true) {
  // "if" block scope
  const message = 'Goal';
  console.log(message); // 'Goal'
}
console.log(message); // throws ReferenceError

The first console.log(message) correctly logs the variable because message is accessed from the scope where it is defined.

But the second console.log(message) throws a reference error because the message variable is accessed outside of its scope: the variable doesn't exist here.

The code block of if, for, and while statements also create a scope.

In the following example for loop defines a scope:

for (const playerName of ['Ronaldo', 'Messi', 'Ramos']) {
  // "for" block scope
  const message = 'Goal';
  console.log(playerName);   // 'Ronaldo', 'Messi', 'Ramos'
  console.log(message); // 'Goal'
}
console.log(playerName);   // throws ReferenceError
console.log(message); // throws ReferenceError

playerName and message variables exist within the scope of the while code block.

In the same way, the code block of the while statement creates a scope for its variables:

while (/* condition */) {
  // "while" block scope
  const message = 'Goal';
  console.log(message); //'Goal'
}
console.log(message); // => throws ReferenceError

message is defined within while() body, consequently message is accessible only within while() body.

In JavaScript, you can define standalone code blocks. The standalone code blocks also delimit a scope:

{
  // block scope
  const message = 'Goal';
  console.log(message); // 'Goal'
}
console.log(message); // throws ReferenceError

var is not block scoped

As seen in the previous section, the code block creates a scope for variables declared using const and let. However, that's not the case for variables declared using var.

The snippet below declares a variable count using a var statement:

if (true) {
  // "if" block scope
  var count = 0;
  console.log(count); // 0
}
console.log(count); // 0

The count variable, as expected, is accessible within the scope of the if code block. However, the count variable is also accessible outside!

A code block does not create scope for var variables, but a function body does. Read the previous sentence again, and try to remember it.

Function Scope in Javascript

Function scope is where variables and functions are scoped to the function that they’re declared in. Variables declared outside of a function are global variables. When a function is declared, all variables are scoped to that function. This means, only the function can access these variables. When coding, you’ll notice that variables declared inside a function are preceded with an underscore. When a function finishes executing, the variables that are scoped to that function are destroyed. This means you cannot access them outside the function.

A function in JavaScript defines a scope for variables declared using var, let, and const.

Let's declare a var variable within a function body:

function run() {
  // "run" function scope
  var message = 'Goal, World Class, Goal!';
  console.log(message); // 'Goal, World Class, Goal!'
}
run();
console.log(message); // throws ReferenceError

run() function body creates a scope. The variable message is accessible inside of the function scope, but inaccessible outside.

Same way, a function body creates a scope for let, const, and even function declarations.

function run() {
  // "run" function scope
  const two = 2;
  let count = 0;
  function run2() {}
  console.log(two);   // 2
  console.log(count); // 0
  console.log(run2);  // function
}
run();
console.log(two);   // throws ReferenceError
console.log(count); // throws ReferenceError
console.log(run2);  // throws ReferenceError

Global Scope in Javascript

Global scope is the default scope in Javascript. This means all variables and functions are scoped to the global scope by default. Code that is declared in the global scope can be accessed from anywhere. In other words, the global scope is the outermost scope. It is accessible from any inner (local) scope.

let playerName = "Ronaldo";
// code here can use playerName

function myFunction() {
// code here can also use playerName
}

If JavaScript is single-threaded, how is it synchronous?

JavaScript is a Single-threaded, non-blocking, synchronous, concurrent programming language with lots of flexibility.

Single-threaded and synchronous are not that much different.

Single-threaded: A single-thread language is one with a single call stack and a single memory heap. It means that it runs only one thing at a time. (don't worry just read and soon you'll get what it is)

Synchronous: As the name suggests synchronous means to be in a sequence. So, a function has to wait for the earlier function to get executed, and everything stops until the wait is over.

Call Stack

the call stack is a data structure that records where in the program we are. If we step into a function we push it to the top of the stack and when we return a value from the function we pop the function of the stack.

Let's understand it by running the below code:

COPY
function multiply(a, b){
     return a*b;
}

function square(n){
     return multiply(n)
}

function printSquare(n){
     let squared = square(n)
     console.log(squared)
}

printSquare(4)

There will be a main() function when the file starts executing then we call printSquare which gets pushed over the top of the stack which in turn calls a square function which gets pushed over at the top of the stack which in turn calls the multiply function which gets pushed over at the top of the stack.

main().png

Now, as soon as a function returns some value it gets popped off from the top of the stack. Even if a function does not have anything to return, it gets popped off from the top of the stack after its executionprintSquare(4).

main() (2).png

Due to this synchronous nature of JavaScript problem arises when we have a very heavy function in between which is taking 20-30 seconds or more time to execute. In this case, everything else is stopped (does not matter where you click in the browser window) for some time, and the call stack gets blocked until that function returns.

To tackle this problem in JavaScript we made JavaScript asynchronous (where tasks seem to run in parallel) with the help of web API. It only appears to be asynchronous, it still has only one call stack. I'll explain this concept in my next blog and will give its link here once ready.

If you have any doubts feel free to post in the comment section, I'll try to answer as many doubts as I can.

Hoisting

Hoisting in Javascript is a behavior in which a function or a variable can be used before declaration. it is the default behavior of javascript to more declarations to the top.

Variable Hoisting

In terms of variables and constants, the keyword var is hoisted, and let and const does not allow hoisting.

a=8;
console.log(a);
var a;

Above, variable a is used before declaring it. And the program works and displays the output 8. If a variable is used with the let keyword, that variable is not hoisted. For example,

a=8;
console.log(a);
let a; // error

Function Hoisting

A function can be called before declaring it. like this:

fun();

function fun() {
       console.log('Hello World');
}

Above, the function fun is called before declaring it and the program shows the output. This is due to hoisting.

Declare Variables At the Top

Hoisting can cause undesirable outcomes in your program. And it is best to declare variables and functions first before using them and avoid hoisting. in the case of variables, it is better to use let than var.

To avoid bugs, always declare all variables at the beginning of every scope.