Javascript Cheatsheet Interview Prepration

Sufyan ShaikhSufyan Shaikh
24 min read

Table Of Content

1. Hoisting

2. Scope

3. Single Threaded

4. Call Stack

1. Hoisting

Introduction to the JavaScrip hoisting

JS (1).png

When the JavaScript engine executes the JavaScript code, it creates the global execution context. The global execution context has two phases:

Creation

Execution

During the creation phase, the JavaScript engine moves the variable and function declarations to the top of your code. This is known as hoisting in JavaScript.

Variable hoisting

Variable hoisting means the JavaScript engine moves the variable declarations to the top of the script. For example, the following example declares the counter variable and initialize its value to 1:

console.log(counter); // 👉 undefined
var counter = 1;

Code language: JavaScript (javascript) In this example, we reference the counter variable before the declaration.

However, the first line of code doesn’t cause an error. The reason is that the JavaScript engine moves the variable declaration to the top of the script.

Technically, the code looks like the following in the execution phase:

var counter;

console.log(counter); // 👉 undefined
counter = 1;

Code language: JavaScript (javascript) During the creation phase of the global execution context, the JavaScript engine places the variable counter in the memory and initializes its value to undefined.

The let keyword

The following declares the variable counter with the let keyword: Code language: JavaScript (javascript) The JavaScript issues the following error:

"ReferenceError: Cannot access 'counter' before initialization The error message explains that the counter variable is already in the heap memory. However, it hasn’t been initialized.

Behind the scenes, the JavaScript engine hoists the variable declarations that use the let keyword. However, it doesn’t initialize the let variables.

Notice that if you access a variable that doesn’t exist, the JavaScript will throw a different error:

console.log(alien);
let counter = 1;

Code language: JavaScript (javascript) Here is the error:

"ReferenceError: alien is not defined Function hoisting Like variables, the JavaScript engine also hoists the function declarations. This means that the JavaScript engine also moves the function declarations to the top of the script. For example:

let x = 20,
  y = 10;

let result = add(x, y); 
console.log(result); // 👉 30

function add(a, b) {
  return a + b;
}

Code language: JavaScript (javascript) Output:


30

In this example, we called the add() function before defining it. The above code is equivalent to the following:

function add(a, b){
    return a + b;
}

let x = 20,
    y = 10;

let result = add(x,y);
console.log(result); // 👉 30

Code language: JavaScript (javascript) During the creation phase of the execution context, the JavaScript engine places the add() function declaration in the heap memory. To be precise, the JavaScript engine creates an object of the Function type and a function reference called add that refers to the function object.

Function expressions The following example changes the add from a regular function to a function expression:


let x = 20,
    y = 10;

let result = add(x,y); // ❌ Uncaught ReferenceError: add is not defined
console.log(result);

let add = function(x, y) {
    return x + y;
}

Code language: JavaScript (javascript) If you execute the code, the following error will occur:

Uncaught ReferenceError: add is not defined Code language: JavaScript (javascript) During the creation phase of the global execution context, the JavaScript engine creates the add variable in the memory and initializes its value to undefined.

When executing the following code, the add is undefined, hence, it isn’t a function:

let result = add(x,y);

Code language: JavaScript (javascript) The add variable is assigned to an anonymous function only during the execution phase of the global execution context.

Arrow functions The following example changes the add function expression to the arrow function:

let x = 20,
    y = 10;

let result = add(x,y); // ❌ Uncaught ReferenceError: add is not defined
console.log(result);

let add = (x, y) => x + y;

Code language: JavaScript (javascript) The code also issues the same error as the function expression example because arrow functions are syntactic sugar for defining function expressions.

Uncaught ReferenceError: add is not defined Code language: JavaScript (javascript) Similar to the functions expressions, arrow functions are not hoisted.

2. Scope

JS.png The JavaScript language has a few concepts of “scope”, none of which are straightforward or easy to understand as a new JavaScript developer (and even some experienced JavaScript developers). This post is aimed at those wanting to learn about the many depths of JavaScript after hearing words such as scope, closure, this, namespace, function scope, global scope, lexical scope and public/private scope.

Hopefully by reading this post you’ll know the answers to:

What is Scope?

What is Global/Local Scope?

What is a Namespace and how does it differ to Scope?

What is the this keyword and how does Scope affect it?

What is Function/Lexical Scope?

What are Closures?

What is Public/Private Scope?

How can I understand/create/do all of the above?

Table of contents

What is Scope?

What is Global Scope?

What is Local Scope?

Function scope

Lexical Scope

Scope Chain

Closures

Scope and ‘this’

Changing scope with .call(), .apply() and .bind()

.call() and .apply()

.bind()

Private and Public Scope

What is Scope?

In JavaScript, scope refers to the current context of your code. Scopes can be globally or locally defined. Understanding JavaScript scope is key to writing bulletproof code and being a better developer. You’ll understand where variables/functions are accessible, be able to change the scope of your code’s context and be able to write faster and more maintainable code, as well as debug much faster.

Thinking about scope is easy, are we inside Scope A or Scope B?

What is Global Scope?

Before you write a line of JavaScript, you’re in what we call the Global Scope. If we declare a variable, it’s defined globally:

// global scope

var name = 'Todd';

Global scope is your best friend and your worst nightmare, learning to control your scopes is easy and in doing so, you’‘ll run into no issues with global scope problems (usually namespace clashes). You’ll often hear people saying “Global Scope is bad”, but never really justifying as to why. Global scope isn’t bad, you need it to create Modules/APIs that are accessible across scopes, you must use it to your advantage and not cause issues.

Everyone’s used jQuery before, as soon as you do this…

jQuery('.myClass');
```… we’re accessing jQuery in global scope, we can refer to this access as the namespace. The namespace is sometimes an interchangeable word for scope, but usually the refers to the highest level scope. In this case, jQuery is in the global scope, and is also our namespace. The jQuery namespace is defined in the global scope, which acts as a namespace for the jQuery library as everything inside it becomes a descendent of that namespace.

### What is Local Scope?
A local scope refers to any scope defined past the global scope. There is typically one global scope, and each function defined has its own (nested) local scope. Any function defined within another function has a local scope which is linked to the outer function.

Angular Directives In-Depth eBook Cover
Free eBook
Directives, simple right? Wrong! On the outside they look simple, but even skilled Angular devs haven’t grasped every concept in this eBook.

Green Tick Icon Observables and Async Pipe
Green Tick Icon Identity Checking and Performance
Green Tick Icon Web Components <ng-template> syntax
Green Tick Icon <ng-container> and Observable Composition
Green Tick Icon Advanced Rendering Patterns
Green Tick Icon Setters and Getters for Styles and Class Bindings
Name
Email
Download Download Icon
If I define a function and create variables inside it, those variables becomes locally scoped. Take this example:

// Scope A: Global scope out here

var myFunction = function () { // Scope B: Local scope in here }; ```Any locally scoped items are not visible in the global scope - unless exposed, meaning if I define functions or variables within a new scope, it’s inaccessible outside of that current scope. A simple example of this is the following:

var myFunction = function () {
  var name = 'Todd';
  console.log(name); // Todd
};

// Uncaught ReferenceError: name is not defined

console.log(name);

The variable name is scoped locally, it isn’t exposed to the parent scope and therefore undefined.

Function scope

All scopes in JavaScript are created with Function Scope only, they aren’t created by for or while loops or expression statements like if or switch. New functions = new scope - that’s the rule. A simple example to demonstrate this scope creation:

// Scope A

var myFunction = function () {
  // Scope B
  var myOtherFunction = function () {
    // Scope C
  };
};

It’s easy to create new scope and create local variables/functions/objects.

Lexical Scope

Whenever you see a function within another function, the inner function has access to the scope in the outer function, this is called Lexical Scope or Closure - also referred to as Static Scope. The easiest way to demonstrate that again:

// Scope A

var myFunction = function () {
  // Scope B
  var name = 'Todd'; // defined in Scope B
  var myOtherFunction = function () {
    // Scope C: `name` is accessible here!
  };
};

You’ll notice that myOtherFunction isn’t being called here, it’s simply defined. Its order of call also has effect on how the scoped variables react, here I’ve defined my function and called it under another console statement:

var myFunction = function () {
  var name = 'Todd';
  var myOtherFunction = function () {
    console.log('My name is ' + name);
  };
  console.log(name);
  myOtherFunction(); // call function
};

// Will then log out: // Todd // My name is Todd

Lexical scope is easy to work with, any variables/objects/functions defined in its parent scope, are available in the scope chain. For example:

var name = 'Todd';
var scope1 = function () {
  // name is available here
  var scope2 = function () {
    // name is available here too
    var scope3 = function () {
      // name is also available here!
    };
  };
};

The only important thing to remember is that Lexical scope does not work backwards. Here we can see how Lexical scope doesn’t work:

// name = undefined
var scope1 = function () {
  // name = undefined
  var scope2 = function () {
    // name = undefined
    var scope3 = function () {
      var name = 'Todd'; // locally scoped
    };
  };
};

I can always return a reference to name, but never the variable itself.

Scope Chain Scope chains establish the scope for a given function. Each function defined has its own nested scope as we know, and any function defined within another function has a local scope which is linked to the outer function - this link is called the chain. It’s always the position in the code that defines the scope. When resolving a variable, JavaScript starts at the innermost scope and searches outwards until it finds the variable/object/function it was looking for.

Closures Closures ties in very closely with Lexical Scope. A better example of how the closure side of things works, can be seen when returning a function reference - a more practical usage. Inside our scope, we can return things so that they’re available in the parent scope:

var sayHello = function (name) {
  var text = 'Hello, ' + name;
  return function () {
    console.log(text);
  };
};

The closure concept we’ve used here makes our scope inside sayHello inaccessible to the public scope. Calling the function alone will do nothing as it returns a function:

sayHello('Todd'); // nothing happens, no errors, just silence... The function returns a function, which means it needs assignment, and then calling:

var helloTodd = sayHello('Todd');
helloTodd(); // will call the closure and log 'Hello, Todd'

Okay, I lied, you can call it, and you may have seen functions like this, but this will call your closure:

sayHello('Bob')(); // calls the returned function without assignment AngularJS uses the above technique for its $compile method, where you pass the current scope reference into the closure:

$compile(template)(scope); Meaning we could guess that their code would (over-simplified) look like this:

var $compile = function (template) {
  // some magic stuff here
  // scope is out of scope, though...
  return function (scope) {
    // access to `template` and `scope` to do magic with too
  };
};

A function doesn’t have to return in order to be called a closure though. Simply accessing variables outside of the immediate lexical scope creates a closure.

Scope and ‘this’ Each scope binds a different value of this depending on how the function is invoked. We’ve all used the this keyword, but not all of us understand it and how it differs when invoked. By default this refers to the outer most global object, the window. We can easily show how invoking functions in different ways binds the this value differently:

var myFunction = function () {
  console.log(this); // this = global, [object Window]
};
myFunction();

var myObject = {};
myObject.myMethod = function () {
  console.log(this); // this = Object { myObject }
};

var nav = document.querySelector('.nav'); // <nav class="nav">
var toggleNav = function () {
  console.log(this); // this = <nav> element
};
nav.addEventListener('click', toggleNav, false);

There are also problems that we run into when dealing with the this value, for instance if I do this, even inside the same function the scope can be changed and the this value can be changed:

var nav = document.querySelector('.nav'); // <nav class="nav">
var toggleNav = function () {
  console.log(this); // <nav> element
  setTimeout(function () {
    console.log(this); // [object Window]
  }, 1000);
};
nav.addEventListener('click', toggleNav, false);

So what’s happened here? We’ve created new scope which is not invoked from our event handler, so it defaults to the window Object as expected. There are several things we can do if we want to access the proper this value which isn’t affected by the new scope. You might have seen this before, where we can cache a reference to the this value using a that variable and refer to the lexical binding:

var nav = document.querySelector('.nav'); // <nav class="nav">
var toggleNav = function () {
  var that = this;
  console.log(that); // <nav> element
  setTimeout(function () {
    console.log(that); // <nav> element
  }, 1000);
};

nav.addEventListener('click', toggleNav, false); This is a neat little trick to be able to use the proper this value and resolve problems with newly created scope.

Changing scope with .call(), .apply() and .bind() Sometimes you need to manipulate the scopes of your JavaScript depending on what you’re looking to do. A simple demonstration of how to change the scope when looping:

var links = document.querySelectorAll('nav li');
for (var i = 0; i < links.length; i++) {
  console.log(this); // [object Window]
}

The this value here doesn’t refer to our elements, we’re not invoking anything or changing the scope. Let’s look at how we can change scope (well, it looks like we change scope, but what we’re really doing is changing the context of how the function is called).

.call() and .apply()

The .call() and .apply() methods are really sweet, they allows you to pass in a scope to a function, which binds the correct this value. Let’s manipulate the above function to make it so that our this value is each element in the array:

var links = document.querySelectorAll('nav li');
for (var i = 0; i < links.length; i++) {
  (function () {
    console.log(this);
  }).call(links[i]);
}

You can see I’m passing in the current element in the Array iteration, links[i], which changes the scope of the function so that the this value becomes that iterated element. We can then use the this binding if we wanted. We can use either .call() or .apply() to change the scope, but any further arguments are where the two differ: .call(scope, arg1, arg2, arg3) takes individual arguments, comma separated, whereas .apply(scope, [arg1, arg2]) takes an Array of arguments.

It’s important to remember that using .call() or .apply() actually invokes your function, so instead of doing this:

myFunction(); // invoke myFunction
You’ll let .call() handle it and chain the method:

myFunction.call(scope); // invoke myFunction using .call()
.bind()

Unlike the above, using .bind() does not invoke a function, it merely binds the values before the function is invoked. It’s a real shame this was introduced in ECMAScript 5 and not earlier as this method is fantastic. As you know we can’t pass parameters into function references, something like this:

// works
nav.addEventListener('click', toggleNav, false);

// will invoke the function immediately
nav.addEventListener('click', toggleNav(arg1, arg2), false);
We can fix this, by creating a new function inside it:

nav.addEventListener('click', function () {
  toggleNav(arg1, arg2);
}, false);

But again this changes scope and we’re creating a needless function again, which will be costly on performance if we were inside a loop and binding event listeners. This is where .bind() shines through, as we can pass in arguments but the functions are not called:

nav.addEventListener('click', toggleNav.bind(scope, arg1, arg2), false); The function isn’t invoked, and the scope can be changed if needed, but arguments are sat waiting to be passed in.

Private and Public Scope In many programming languages, you’ll hear about public and private scope, in JavaScript there is no such thing. We can, however, emulate public and private scope through things like Closures.

By using JavaScript design patterns, such as the Module pattern for example, we can create public and private scope. A simple way to create private scope, is by wrapping our functions inside a function. As we’ve learned, functions create scope, which keeps things out of the global scope:

(function () {
  // private scope inside here
})();
We might then add a few functions for use in our app:

(function () {
  var myFunction = function () {
    // do some stuff here
  };
})();

But when we come to calling our function, it would be out of scope:

(function () {
  var myFunction = function () {
    // do some stuff here
  };
})();

myFunction(); // Uncaught ReferenceError: myFunction is not defined

Success! We’ve created private scope. But what if I want the function to be public? There’s a great pattern (called the Module Pattern [and Revealing Module Pattern]) which allows us to scope our functions correctly, using private and public scope and an Object. Here I grab my global namespace, called Module, which contains all of my relevant code for that module:

// define module
var Module = (function () {
  return {
    myMethod: function () {
      console.log('myMethod has been called.');
    }
  };
})();

// call module + methods
Module.myMethod();

The return statement here is what returns our public methods, which are accessible in the global scope - but are namespaced. This means our Module takes care of our namespace, and can contain as many methods as we want. We can extend the Module as we wish:

// define module
var Module = (function () {
  return {
    myMethod: function () {

    },
    someOtherMethod: function () {

    }
  };
})();

// call module + methods
Module.myMethod();
Module.someOtherMethod();

So what about private methods? This is where a lot of developers go wrong and pollute the global namespace by dumping all their functions in the global scope. Functions that help our code work do not need to be in the global scope, only the API calls do - things that need to be accessed globally in order to work. Here’s how we can create private scope, by not returning functions:

var Module = (function () {
  var privateMethod = function () {

  };
  return {
    publicMethod: function () {

    }
  };
})();
```This means that publicMethod can be called, but privateMethod cannot, as it’s privately scoped! These privately scoped functions are things like helpers, addClass, removeClass, Ajax/XHR calls, Arrays, Objects, anything you can think of.

Here’s an interesting twist though, anything in the same scope has access to anything in the same scope, even after the function has been returned. Which means, our public methods have access to our private ones, so they can still interact but are unaccessible in the global scope.

var Module = (function () { var privateMethod = function () {

}; return { publicMethod: function () { // has access to privateMethod, we can call it: // privateMethod(); } }; })();

This allows a very powerful level of interactivity, as well as code security. A very important part of JavaScript is ensuring security, which is exactly why we can’t afford to put all functions in the global scope as they’ll be publicly available, which makes them open to vulnerable attacks.

Here’s an example of returning an Object, making use of public and private methods:

var Module = (function () { var myModule = {}; var privateMethod = function () {

}; myModule.publicMethod = function () {

}; myModule.anotherPublicMethod = function () {

}; return myModule; // returns the Object with public methods })();

// usage Module.publicMethod();

One neat naming convention is to begin private methods with an underscore, which visually helps you differentiate between public and private:

var Module = (function () { var _privateMethod = function () {

}; var publicMethod = function () {

}; })();


This helps us when returning an anonymous Object, which the Module can use in Object fashion as we can simply assign the function references:


var Module = (function () {
  var _privateMethod = function () {

  };
  var publicMethod = function () {

  };
  return {
    publicMethod: publicMethod,
    anotherPublicMethod: anotherPublicMethod
  }
})();

Happy scoping!

3. Single Threaded Language

JS (2).png

What does it mean by Javascript is single threaded language

If you have been using Javascript for a while then you may come across the phrase that it’s a single threaded language.

What does that means?

Javascript engine runs on a V8 engine that has a memory heap and a call stack.

JS is a single threaded which means only one statement is executed at a time.

Before we dive into what it means by it runs on single thread. I would want to first go over the terminology that will help you in understanding.

My attempt will be to explain in the simplest manner possible. To understand this better you need to know a Data Structure known as Stack (Last In, First Out).

Synchronous (or sync) execution usually refers to code executing in sequence. In sync programming, the program is executed line by line, one line at a time. Each time a function is called, the program execution waits until that function returns before continuing to the next line of code.

To put it in example, you are calling someone and you’re waiting for them to pick up so that you can talk to them. You’re not doing any other thing until they pick up the phone.

You fulfill the request sequentially.

const one() => {
     const two() => {
       console.log('5');
 }
    two();
}

So, what happens under the call stack?

The call stack job is to fill in the instructions and pop an instruction as it gets executed.

Javascript is a single threaded language that can be non-blocking. Single threaded means it has only one call stack. Whatever is on the top of the call stack is run first.

In the above program, functions are run sequentially.

What if we have a function that is require to do heavy lifting. Should we let the user wait till that process is over?

const one() {
      console.log("Hello");
}
const two () {
    for(i=0; i<= 100000000000000000000000; i++){
}
const three(){
       console.log("World");
}
one();
two();
three();

Consider the above example, what if our second function has to loop through huge numbers. Does this means three() has to wait till two() is executed. Technically, Yes!

In our small example it may not mean much but if we have to implement in a real project then the users may not be able to do anything until the first process is finished.

Asynchronous (or async) execution refers to execution that doesn’t run in the sequence it appears in the code. In async programming the program doesn’t wait for the task to complete and can move on to the next task.

To put it in example: You call someone and while you’re waiting for them pick up the phone, you’re also running errands.

Different languages have different ways to implement asynchronous. The most popular is through Multi-threading.

In brief, Java implements multi-threading by creating a child thread which does it’s own separate execution and then merges back with the parent thread.

This however can run into a problem known as Deadlock, which can be dealt with various deadlock prevention mechanism.

Since, we are concerned about implementing asynchronous in Javascript. Let’s see how we can do it.

Try running this in console and see what happens.

console.log('1');
setTimeout(()=> {
console.log('2')
}, 3000);
console.log('3');

You may see 1 3 and with a brief delay 2 shows up. Why is this happening?

In a nutshell, the asynchronous implementation in Javascript is done through a call stack, call back queue and Web API and event loop.

Call stack job as we seen earlier is to check what instruction is at the top of the stack and execute it. If there is an instruction like setTimeout() that requires extra time to execute then call stack will pop that out and send it to Web API.

The job of event loop is to continuously check if an event occurred, like mouse click or keyboard stroke so that it can send that to call stack. Of course, your mouse click will be given higher priority for execution than an image load.

The Coding Cards Master essential Coding Concepts with syntax and examples. Get better at Tech Interviews with this easy to use coding… thecodingcards.com

In Javascript, All instructions are put on a call stack. When the stack arrives at setTimeout, the engine sees it as a Web API instruction and pops it out and sends it to Web API. Once the Web API is done with the execution, it will arrive at the call back queue.

The engine checks if the call stack is empty. If it is empty, then we check callback queue which has the instruction setTimeout in it. The callback queue sends it to call back stack and the instruction is executed.

The other way to think about this is when you make an API request. Say for example your website needs to fetch an image from a server. Should your website refuse to load other parts till the image arrives? That would be a bad user experience.

When call stack sees it needs to fetch an image, it pops and send it to Web API and continues executing the remaining functions.

The response of image request is stored in call stack queue.

When the call stack is empty, the event loop which is continuously running looks over the Call stack queue if it has anything. If it does, in our case the response of image request. It puts over the call stack and execute the instruction.

The benefit of this procedure is JavaScript need not worry about how many cores or nodes a CPU is running on. There is only single call stack for this implementation.

4. Call Stack

call stack.png

What is the Call Stack?

A call stack is a mechanism for an interpreter (like the JavaScript interpreter in a web browser) to keep track of its place in a script that calls multiple functions — what function is currently being run and what functions are called from within that function, etc. — MDN Web Docs

The call stack keeps track of functions to be executed. When we call a function, it’s added, or pushed to the top of the call stack. When the function returns, it’s removed, or popped from the call stack. Any asynchronous functions (fetch, setTimeout, async, etc.) are moved to the event queue (more on that later).

Most likely, you’ve seen the call stack in your console when an error is thrown.

From the above image, we can see the current state of the call stack (a, b, c) and when the error occurred.

How does the Call Stack Work?

You might have heard that JavaScript is single-threaded. This means it has only one call stack and it can only process one statement at a time. The call stack follows the LIFO (Last In, First Out) principle, which means it will always process the call on top of the stack first.

When a function is called it’s added to the stack. When a function calls another function, it’s added on top of the calling function.

Given the above block of code, we can assert that:

First, sayHi is invoked and added to the call stack (sayHi has not yet resolved). sayHi then invokes sayBye and adds sayBye to the call stack (both functions are still unresolved). At this point, the call stack status is currently:

  1. sayBye is now at the top of the call stack. It will execute and print out ‘Bye’ to the console. Then, it is removed from the top of the call stack.
  1. Now, sayHi is at the top of the call stack. It will print out ‘Hi’ to the console then be removed from the call stack. The call stack is now empty.

  2. The final output:

How does the Event Loop work?

When an async function is called it does not go to the call stack. Instead, it’s forwarded to the event queue. The connection between the call stack and event queue is facilitated by the event loop. The event loop is constantly checking the call stack. If the call stack is empty it adds the first function in the event queue to the call stack for execution. Otherwise, it continues processing code in the call stack.

What is the Event Queue?

The event queue is where async code waits for execution. Unlike the call stack the event queue follows the FIFO (First In, First Out) principle, which means it will always process calls in the same order they were added to the queue.

It’s important to note that the event queue will only begin executing when the call stack is empty. If the call stack is already processing code, the event loop will not add any functions from the event queue. The event loop will not resume until the call stack has cleared.

Take a look at the following code.

As expected, the above code will immediately print out ‘foo’ in the console. Then, 1 second later it will print out ‘bar’.

How about the below code?

Here, setTimeout is set to 0. Because of this, you might think bar() will execute immediately resulting in ‘bar’ being printed before ‘foo’. But this is not the case. Both code snippets will result in:

Although setTimeout is set to 0, it is still forwarded to the event queue. This means it cannot execute until the call stack has completely cleared.

2
Subscribe to my newsletter

Read articles from Sufyan Shaikh directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sufyan Shaikh
Sufyan Shaikh