Concepts to revise before appearing for a JavaScript Interview (Part — 1)

Photo by Irvan Smith on Unsplash

When going for Frontend Interviews, it’s extremely important that you have the fundamentals of JavaScript down really well. Interviewers will spend a good amount of time testing your depth of knowledge in the language.

In this article, I’ve tried to list and briefly discuss some of the topics that one should definitely know -

this

The value that this stores is the current execution context of the JavaScript program. Thus, the value of this inside a function is determined by how the function is defined, how it is invoked and the default execution context.

Here’s a summary of how ‘this’ works in JavaScript -

The methods — bind(), call() and apply() are used to bind a function while passing the desired scope to the inner function. Let’s look at them in detail -

bind()

The bind() function is used when you want to maintain the context in asynchronous functions and callbacks.

Let’s now look at an example how bind() is used -

var person = {
firstName: "Rishav",
lastName: "Bharti",
get: function () {
console.log("Outer: " + this.firstName + " " + this.lastName);
var print = function (role, language) {
console.log("Inner: " + this.firstName + " " + this.lastName + ". I'm a " + language + " " + role + ".")
}.bind(this, "Developer", "MERN Stack");
print();
},
};
person.get();

Try guessing the output of the program. Answer to it will be revealed towards the end of this article.

call() and apply() is used when you want to use a function inside an object and call that function in an entirely different object.

call()

The bind() and call() methods differ from each other on the basis of the fact that you explicitly need to call the function on which the bind() method is applied. This is because the bind() method returns the function which needs to be called later. However, you do not need to do so in case of the call() method. The function on which you apply the call() method is invoked implicitly when the control reaches it. Thus, you do not need to explicitly call the function on which you apply the call() method.

Here’s an example showing the usage of call() -

var person = {
firstName: "Rishav",
lastName: "Bharti",
get: function () {
console.log("Outer: " + this.firstName + " " + this.lastName);
var print = function (role, language) {
console.log("Inner: " + this.firstName + " " + this.lastName + ". I'm a " + language + " " + role + ".")
}.call(this, "Developer", "MERN Stack");
},
};
person.get();

What do you think will be the output of the above program? We’ll find out soon.

apply()

The only difference between the call() method and apply() method is that call() method accepts arguments passed individually and separated with a comma. On the other hand, the apply() method is called with an array of arguments.

var person = {
firstName: "Rishav",
lastName: "Bharti",
get: function () {
console.log("Outer: " + this.firstName + " " + this.lastName);
var print = function (role, language) {
console.log("Inner: " + this.firstName + " " + this.lastName + ". I'm a " + language + " " + role + ".")
}.apply(this, ["Developer", "MERN Stack"]);
},
};
person.get();

Are you able to guess the output of the above code snippet?

The output of all the above programs will be —

Outer: Rishav Bharti \n Inner: Rishav Bharti. I’m a MERN Stack Developer.

Closures

A closure is basically an inner function that has access to the outer (enclosing) function’s resources due to the scope chain where a child can access all the resources of its parent. It is basically the combination of a function and the lexical environment in which the function was declared. This closure function has access to all the local variables that were declared inside this lexical scope when the closure function was created.

The power of closures is derived from the fact that the inner function remembers the environment in which it was created. In other words, the inner function has access to the outer function’s variables and parameters.

Closures are significant in the situations when you require the inner function to access the outer function’s variables (or resources) as long as the inner function wants, even when the outer function has finished executing.

Consider a scenario where you mock the functionality of adding an item to the cart. A simplified code can be considered as the one given below:

function modifyItem() {
var items = 0, inStock = 10;
return {
add: function() {
if(inStock > 0) {
console.log(“Added item to cart!”);
items++;
inStock — ;
}
else {
console.log(“Item Out of Stock!”);
}
},
getCount: function() {
return “Items in cart = “ + items;
}
}
}
var item = modifyItem();
item.add();
console.log(item.getCount()); // prints 1
item.add();
item.add();
console.log(item.getCount()); // prints 3

Here, the function modifyItem() modifies an item inside the cart. It returns an object consisting of two keys — add and getCount, which contain methods to add an item to the cart and to get the count of the total number of items in the cart.

The value returned by the function modifyItem(), which is an object, is held inside the variable item. On this variable item, the getCount() method is called. Notice that the methods — add() and getCount() are accessible even after the statement modifyItem() is executed meaning that these are accessible even after the function modifyItem() has finished executing.

Thus, you can use the closure function (closure methods — add() and getCount()) even when the outer function (function modifyItem()) in which it was defined has finished its execution and you can still access the resource(s) (items) defined inside the scope of the outer function, in which the closure was created.

Hoisting

Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their scope before code execution and are remembered by the compiler. This is how, when you run the code, all the variables are accessible even though it seems like the variables haven’t been declared yet. But remember that all these variables are initialized with the value as undefined. And this is why, if you try to access a variable without initializing it, you get the value as undefined.

Prototypes & Prototypal inheritance

In JavaScript, objects have a special hidden property [[Prototype]] (as named in the specification), that is either null or references another object. That object is called “a prototype”.

The __proto__ property either refers to an object or is null. The prototype property of an object is where we put methods and properties that we want other objects to inherit. A prototype of an object can be assigned to another object, thus, making the latter access the resources of the former. This is what is called prototypal inheritance.

  • The Constructor’s prototype property is NOT the prototype of the Constructor itself, it’s the prototype of ALL instances that are created through it.

When a certain method (or property) is called, the search moves on to the object’s prototype. This continues until the method is found: prototype chain. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype. By definition, null has no prototype, and acts as the final link in this prototype chain. Nearly all objects in JavaScript are instances of Object, which sits on the top of a prototype chain.

In the next article, we’ll discuss some more important concepts.

P.S. — I’ve written this article as a note to myself about the topics I must revise before appearing for an interview

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store