Here is a list of beginner level JavaScript interview questions.
1. What are the
various ways of declaring a variable available in JS?
Answer:
Since the good old days,
JS has had the var keyword
for declaring new variables.
var name = "Emma Watson";
However, due to the
limitations and nuances of that, ES6 introduced two new keywords for declaring
new variables let & const:
let name = "Emma Watson";
const name = "Emma Watson";
const : Declares an immutable variable whose value cannot be
changed during the entire course of execution of the program. Doing so throws a
TypeError.
let : Declares a mutable variable within the nearest enclosing
block.
var : Declares a mutable variable within the nearest function
block.
Declaring global variable
as var pollutes
the global namespace and can result in bizarre errors in large codebases. let prevents that as it
is only visible in the nearest block scope. Also, if declared globally, it is
not attached to the window object.
var notAwesome = 1;
console.log(window.notAwesome); // 1
let awesome = 1;
console.log(window.awesome); // undefined
2. How can you declare
an array in JavaScript?
Answer:
We can declare an array in JavaScript using the square bracket
syntax.
const numbers = [1, 2, 3, 4, 5];
We can also use the Array constructor,
supplying it the number of elements we want our array to contain. However, note
that this initializes the array with undefined. To get rid of that, you can use the fill method to populate
the array with real values.
let numbers = new Array(10);
console.log(numbers); // [undefined x 10];
numbers = new Array(10).fill(0);
console.log(numbers); // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
3. What are JavaScript
Objects?
Answer:
JavaScript objects are
containers that house name,value pairs inside them. They can be used to
accumulate information about an entity in one place.
For example, if you need to store information about a user in
JavaScript, a brute-force way is to use multiple variables and store the
information in them.
const name = "Abhishek Soni";
const phone = "00000000000";
const email = "email@email.com";
However, maintaining those variables for 10 or 100 users will
become a bottleneck. We can store that information in one variable (container
of information) using JS objects:
const user = {
name: "Abhishek Soni",
phone: "00000000000",
email: "email@email.com"
};
4. Does JavaScript
have a Boolean data type?
Answer:
Yes. JavaScript has a
special data type to represent boolean variables. The two special values
are true and false. They can be assigned to
any JS variable to make it boolean:
let isFlagged = true;
let isNotFlagged = false;
5. What are the
various types of flow control/looping statements available in JS?
Answer:
JavaScript supports three types of looping statements:
1. If-Else
2. For
3. While
4. Do-While
If-Else
if (name === "Abhishek Soni") {
return "Admin";
} else {
return "Employee";
}
For
We can use the for loop to perform an
operation to a list of values or execute a block of code multiple times.
for ( let i = 0; i < 10; i++) {
// Executing block
console.log(i);
}
The above program loops over the executing block, until a pre-defined condition is true.(Here: `i < 10`)
Each iteration increments the value of `i` (`i++`). Once the condition is reached, the loop ends.
While
let i = 0;
while (i < 10) {
i++;
console.log(i);
}
Another way of achieving
what the for loop
did in the above code snippet is to use the while loop. While loop is similar
to for loop
in the sense that it continues the execution of its execution block until a
pre-defined condition fails.
Do-While
let i = 1;
do {
i++;
console.log(i);
} while (i < 10);
do-while loop works just like while except it executes
at least once. (Just like any other programming language.)
6. Write a program to
reverse a string in JS.
Answer:
Steps involved in
revering a string in JS are: (1) split the string into its consituent
characters (Array), (2)
call the reverse method
to reverse the order of characters in the string and (3) join the characters
back. This is illustrated below.
function reverse(string) {
return string
.split("")
.reverse()
.join("");
}
Here is list of intermediate level JavaScript interview
questions.
1. What is the
difference between == and === check in JS?
Answer:
== : Simple equality check with type conversion supported
console.log(1 == "1"); // true
=== : Strict equality check with no type conversion
console.log(1 === "1"); // false
2. Is this the correct
way of copying an object in JS?
Answer:
const object1 = { a: 1, b: 2 };
const object2 = object1;
No. object2 is merely a
reference to the same object. Changing a property using object2 will also result in
the same property getting changed for object1 . This happens because object2 simply points to
the object created by object1 . It doesn’t hold it’s own copy of the
object. This is illusrated below:
object2.a = 2;
console.log(object2.a); // 2
console.log(object1.a); // 2
The correct way of
cloning an object (introduced in ES6) is by using the Object.assignmethod:
const object1 = { a: 1, b: 2 };
const object2 = Object.assign({}, object1);
3. What will be the
output of the following code?
Answer:
console.log(1);
console.log(2);
setTimeout(() => {
console.log(3);
}, 0);
console.log(4);
The output, surprisingly, will be
1;
2;
4;
3;
This happens because JS treats callback functions (like the one
sent to setTimeout) differently. You can think of them as second-class citizens
in JavaScript wherein they are always called (executed) after the first-class
citizens (other functions) are finished. This is the reason why a 0 ms delay-
timeout function doesn’t execute its callback immediately. It has to wait for
all the other functions to return first.
4. Will the following
program crash? Explain your answer.
function sum(a, b) {
return a + b;
}
sum.functionName = "Add";
Answer:
The program will not crash. Attaching a property to a function is perfectly legal in JS. In fact, that property can be read back later, if need be. This is possible because functions in JS are just a special type of Objects and hence, properties can be attached to them.
The program will not crash. Attaching a property to a function is perfectly legal in JS. In fact, that property can be read back later, if need be. This is possible because functions in JS are just a special type of Objects and hence, properties can be attached to them.
console.log(sum.functionName); // Add
5. What are callback
functions?
Answer:
A callback function is a function passed to another function,
where it is executed after some pre-defined processing has been completed. In
node.js callbacks are used to return results of asynchronous methods such as
I/O operations, etc.
function readFile(name, callback) {
let file;
// READ FILE HERE
ASYNCHRONOUSLY
setTimeout(() => {
callback(file);
}, 2000);
/**
* return file; (Using this will immediately
return undefined as
* the file variable does not contain
anything yet.)
*/
}
6. What is the spread
operator in JS?
Answer:
The spread operator, or the
three dots, (…) is a new operator introduced in ES6. It allows the expansion of
an iterable (e.g., Array) into
its constituent elements.
const t = [1, 2, 3];
const s = [...t, 4, 5, 6];
console.log(s); // [1, 2, 3, 4, 5, 6];
7. Given an array with
duplicates, what is the easiest way to remove the duplicates from it?
const numbers = [1, 2, 3, 4, 5, 5, 5, 5, 5, 5];
Answer:
Here’s a one-liner to remove duplicates from an array. (ES6, of
course!)
function removeDuplicates(array) {
return [...new Set(array)];
}
Set was introduced in ES6 and is similar to the Sets we
encounter in Mathematics: They can’t have duplicates. After we have done that,
we simply convert the Set back to an array by using the spread operator.
8. What does the
following code do?
const person = {
name: "Abhishek Soni",
age: 23,
place: "Edmonton",
phone: 0000000000
};
delete person.phone;
Answer:
We are first declaring an
object and then removing a key named phone from the object. (Note that deleting a key like this is
not recommended as the call would still succeed even if the phone key didn’t exist on
the person object. To make sure you are deleting the right key, you might want
to iterate over the key and only delete if the target key is found.)
for (let key in person) {
if (key === "phone") {
delete person[key];
}
}
9. How do you cancel
invocation of a method set to be executed every 10ms using setInterval?
Answer:
We can think of setInterval as an alarm that
keeps firing after a pre-defined interval has passed. When setting this
alarm, setInterval returns
an id of the alarm. This ID can be later used to cancel the alarm, if need be,
using the cancelInterval method:
const loggerID = setInterval(() => {
console.log(logs);
}, 10);
// Somewhere down the road
clearInterval(loggerID);
10. What is the difference between forEach and filter?
Answer:
forEach, filter, and map are all iterator methods that are attached to Arrays in
JavaScript. They can be called from any Array with a callback function. The
callback function receives the array elements (and the indexes) depending on
the function being called.
forEach: Iterates over the entire array, invoking the
callback function on each element present in the array. Doesn't return
anything.
const numbers = [1, 2, 3];
numbers.forEach(num => {
console.log(num * 2);
});
// Logs 2, 4, 6;
map: Iterates over the entire array, invoking the callback function
on each element. The return value of the callback function is pushed to a new
result array. Returns a new result array.
const numbers = [1, 2, 3];
const twiceNumbers = numbers.map(num => num * 2);
console.log(twiceNumbers); // [2, 4, 6];
filter: Iterates over the entire array, invoking the
callback function on each element. If the callback function returns true for a particular
element, that element is "filtered" out. Returns a new array.
const numbers = [1, 2, 3];
const evenNumbers = numbers.filter(num => num % 2 === 0); // true only for even numbers
console.log(evenNumbers); // [2]
reduce:
Advanced JavaScript
Interview Questions
Here is a list of Advanced level JavaScript interview questions.
1. What is a Promise?
Make the following function return a Promise.
function delay() {
setTimeout(() => {
return 10;
}, 2000);
}
Answer:
A Promise is an object that
may either return a value sometime in the future. When you return a Promise, its status is pending
and it hasn’t yet returned any value. This return value of a Promise depends on whether
the Promise is
resolved or rejected. If the Promise is resolved, the value will be returned.
If the Promise is
rejected, it returns an Error object explaining why the call was rejected.
fetch("URL")
.then(data => {
console.log(data); // sometime in the future
})
.catch(err => () => {
// handle error
});
Promises help us in preventing callback hell and also make the
code more readable. Because of the asynchronous nature of callback functions,
Promises make them look linear for better understanding. Here’s a promisified
version of the above delay function:
function delay() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 2000);
});
}
2. How is the
async/await paradigm different from Promises?
Answer:
The async/await paradigm involves
two separate keywords that change the meaning of the expression they are used
with. First, let us talk about async:
async function makeRequest() {
// complicated fetch code here
}
Attaching the async keyword in front of
a function makes it always return a Promise. This can be used to make a normal
asynchronous function to return a Promise. But the real power of async/await paradigm can be
harnessed by using await.
const data = await makeRequest();
The await keyword makes the
function wait for the Promise to be resolved and then return its
results to the data variable. Otherwise, we would have had to attach a .thento the call, similar to
how we do in case of Promises. await just makes our life easier and does the waiting for us
itself. This makes our code more linear and easier to read and understand. (It
still is asynchronous, of course!).
3. What is closure?
What is the most prominent application of closure in JS?
Answer:
Closure is simply an inner function accessing (and using) the
variables out of its scope, usually declared in an outer function or block.
This is illustrated below:
const greet = name => {
return {
sincerely: () => {
return `Hello, ${name}!`;
},
withAnger: () => {
return `${name}`;
}
};
};
greet("Abhishek").sincerely(); // Hello, Abhishek!
Here, the two
functions, sincerely and withAnger have access to the
name variable, even though it was declared out of their scope. Also, note that
the original greetmethod
has long returned when the sincerely method is invoked. Despite that,
the name variabe
is still accessible as if it was magically *enclosed *by the inner function.
That, my friend, is Closure.
4. How does the map
method work in JS? Implement map from scratch.
Answer:
The map method attached to
Arrays in JS is used to apply a transformation function to every element of the
array and return the results.
const integers = [1, 2, 3];
const integersDoubled = integers.map(i => i * 2);
console.log(integersDoubled); // [2, 4, 6];
The map method can be
implemented as follows:
const myMap = (array, callback) => {
const result = [];
for (let i = 0; i < array.length; i++) {
result.push(callback(array[i]));
}
return result;
};
5. How can you prevent
your global variables from polluting the global namespace?
Answer:
Immediately Invoked Function Expressions, also known as IIFEs
are a class of functions that are, as the name suggests, immediately invoked
(or called) as soon as they are declared. The most common use case of IIFEs is
to block-scope variables and to hide functionality from the outside world.
(function() {
const age = 27;
})();
age; // ReferenceError
We can use this to hide our script’s global variables from
polluting the global namespace without compromising on functionality.
6. What are
short-circuiting expressions? How are they useful in JS?
Answer:
Short-circuiting
expressions, not a JS thing per se, are expressions in which the second
argument is only evaluated if required. They are used with boolean operators,
specifically AND (&&)
and OR (||)This
is illustrated below:
firstArgument && secondArgument;
firstArgument || secondArgument;
In the first expression,
if firstArgument evaluates
to false, then secondArgument is
not evaluated at all.
This can be used when we are trying to access property names
from dynamically-returned data, for example, by a fetch request.
const data = { name: { second: "Watson" } };
console.log(data.phone.area); // TypeError
To prevent the above error, what we can do is use
short-circuiting expressions:
const data = { name: { second: "Watson" } };
console.log(data.phone && data.phone.area); // will either result in the value or return undefined but there
will be no Error.
In the second expression
using ||,
if firstArgument evaluates
to false, secondArgumentis
evaluated. If firstArgument evaluates
to true, then the secondArgument is
not evaluated at all. This can be used to assign default values to variables.
const data = { name: "Emma Watson" };
const name = data.name || "Unknown";
7. Implement a Singly
LinkedList in JavaScript.
Answer:
Every LinkedList has a head, which
corresponds to the first node in the list, and a pointer (strategically called next) that points to the next
element in the list. This simple and powerful data structure can be implemented
in JS as follows. First, we represent a single Node in the list:
class Node {
constructor(item, next = null) {
this.data = item;
this.next = next;
}
}
The node has a data
attribute and a next attribute.
The data attribute
tells us what this node contains,
and the next attribute
tells us where the next element
in the list is.
And now that we have a node set up, we can link it together to
form our LinkedList:
class LinkedList {
constructor() {
this.head = null;
}
}
A new LinkedList can be initialized
as follows:
const list = new LinkedList(); // empty list
To insert a node into this list, we
can attach a node to
the head of
the list:
list.head = new Node(2); // List = 2-> null
Adding a new element is easy:
list.head.next = new Node(5); // List = 2-> 5 -> null
This can be wrapped up in a function and is left as an exercise
for the reader.
8. What is hoisting in
JavaScript?
Answer:
Hoisting in
JS refers to the fact that the variable declerations are hoisted to
the top of the scope in which they are declared.
function greet() {
console.log(name);
var name = "Abhishek Soni";
}
greet(); // Undefined
Technically, since the
variable has not been declared when the console.log method is called, it should
throw a ReferenceError. However, because of hoisting, message's declartion is hoisted
to the top of the function block: (As if it was first declared.)
function greet() {
var name;
console.log(name);
var name = "Abhishek Soni";
}
9. What is the this keyword in JS?
Answer:
this is a special keyword that refers to the object from where
it is called. For example,
function sum() {
console.log(this); // Logs the Window object
}
sum();
This happens
because sum is
declared in the global scope and is thus, attached to the window object. When
we call the sum function,
what we are actually calling is this:
window.sum();
What is on the left hand
side of the dot is
what this gets
assigned to.
In case of calling a method defined inside a class, this refers
to the class itself. This is similar to objects.
const user = {
name: "Emma",
greet: function() {
console.log(this.name);
}
};
user.greet();
Classes:
class User {
constructor(name) {
this.name = name;
}
greet() {
console.log(this.name);
}
}
const user = new User("Abhishek");
user.greet();
10. What is Prototypal
inheritance in JS? How is it different from class based inheritance?
Answer:
With a few exceptions,
almost all the data types in JS inherit from one Parent type called Object. Before ES6, JS did not
have an implicit inheritance model. To represent real-world objects in code,
and then extend it, JS allowed prototypal inheritance. To illustrate that, let
us imagine we need to represent Vehicles in JS. Since most of the Vehicles will
have some common features, we can create a parent class and multiple child
classes can inherit from the parent class.
Pre ES6:
In case of Prototypal inheritance, we can attach methods to a
generic object and treat it as the Parent.
function Vehicle(name) {
this.name = name;
this.speed = 0;
}
Vehicle.prototype.accelerate = function(speed) {
this.speed += speed;
};
Vehicle.prototype.decelerate = function(speed) {
this.speed -= speed;
};
/**
* Now let us create a car that extends
Vehicle.
*/
function Car(name, color) {
this.name = name;
this.color = color;
}
// Make Vehicle its prototype
Car.prototype = Object.create(new Vehicle());
let ferrari = new Car("ferrari", "red");
Car's prototype is now Vehicle. And Vehicle's prototype is Object.
When we call the
accelerate method on an instance of Car, JS first looks for implementation of
the method in Car. If it is not found, it goes up the prototypal chain and
checks if it is attached to Vehicle. Since it finds the method, it executes it
in the context of Car. This
way, we can reuse functionality by only defining it once and mimic the
Object-Oriented Paradigm in JavaScript.
Car -> Vehicle -> Object -> null
Post ES6:
class Vehicle {
constructor(name) {
this.name = name;
this.speed = 0;
}
accelerate = speed => {
this.speed += speed;
};
decelerate = speed => {
this.speed -= speed;
};
}
Now that we have our Parent class set up, we can extend it to
create a variety of vehicles with the common methods residing in the Parent
Class.
class Car extends Vehicle {
constructor(name, color) {
super(name);
this.color = color;
}
}
Look how subtely we added
a new property named color while reusing the logic we had for Vehicle.
Tips to nail the
JavaScript interview
Below are a few important tips to perform well in your
interview.
1. Be
a problem-solver: Do not panic if you don’t know the answer. Often, the
interviewer is interested in your problem-solving abilities rather than how
fast you get to the answer.
2. Your
thoughts matter: When going through a piece of code, always remember that it is
extremely important to voice your thoughts so that the interviewer knows how
you plan to solve the problem. Think out loud and do not be afraid of being
wrong.
3. Do
not cover up: If you have not heard of a concept that the interviewer is
asking, accept it and move on. It’s better to accept your mistakes than to
cover them up.
4. Keep
calm: Lastly, do not forget to be calm and composed rather than act
all scared. It is just JavaScript. Some objects here and there, with functions
on the side, and sprinkled bundlers: Boom!
No comments:
Post a Comment