Javascript Interview Cheat-Sheet/Questions and Answers



Javascript Interview Cheat-Sheet
Explain let var and const with difference between them
These three are variable declaration techniques in javascript. Before ES6 we only had var, but after its introduction, we have let and const as well. ES6 introduced let and const to resolve re-declaration issues within a large javascript program.
Let | Var | Const |
---|---|---|
block scoped | functional/Global scoped | blocked scope |
cannot be re declared in same scope | Can be redeclared | cannot be re declared in same scope |
initialization is not important | initialization is not important | initialization is important |
Can be updated | Can be updated | Cannot be updated* |
*It can be updated when the value is object
or array
or set
since these are mutable.
Explain Hoisting in Javascript
Hoisting is a property in javascript when a variable seems to be declared even before we try to access it in a statement.
example :
console.log(x) //undefined
const x = 99
we got undefined rather than not defined because javascript first stores all the declarations and initiates with undefined
in its scope memory table and then starts executing statements. This also works with anonymous functions that we store in a variable.
Explain how variables get shadowed in Javascript
When we declare a variable inside a local scope, it takes over the variable that was declared with same name, outside the scope. This behavior is called shadowing.
let x = 10
function someFunc(){
let x = 99
console.log(x) //99
}
Here, the x
inside function, shadowed the x
that was present outside.
What is coercion in javascript?
Coercion in javascript means the automatic conversion of a datatype to another. Javascript is a loosely typed (dynamically typed) which means the datatype of a variable can be changed anytime.
8 + '99' //899
Here, 8
got converted to string and final result was concatenated to be 899
. The automatic coercions are called implicit coercions, while the ones we intend to do with the help of functions like toString()
, Number()
etc. are called explicit coercion.
There are a few shorthand tricks to explicitly coerce values.
typeof(!!'true') // boolean
typeof(+'99') // number
Create a counter and log 0 to 10 in the interval of 1s and explain.
for (let i = 0; i <= 10; i++) {
setTimeout(function() {
console.log(i+1)
}, i * 1000)
}
- We start a loop so that it runs the number of times we intend to.
- We use set timeout function to ensure that each log is printed after some interval (say 1s).
- We used
i*1000
because it means nth number will be printed on n*1000th millisecond. - We used let to ensure that each iteration has a new instance of
i
instead of the redeclared ones if we usedvar
. - Each time set timeout function runs, JS engine waits till the specified time to send the callback function in the callback queue to be executed. The callback function waits until previous callback functions are executed, hence the simultaneous behavior.
Explain callback functions and Callback hell
Callback functions are the functions that are meant to be triggered when some task gets finished in another function
function fetchData(callback) {
// Simulate fetching data asynchronously after 2 seconds
setTimeout(function() {
const data = "Fetched data";
callback(data);
}, 2000);
}
function processData(data) {
console.log("Processing data:", data);
}
fetchData(processData);
processData
is a callback function here.
So this is great until we have a lot of functions that depends on previous one’s completion. It leads us to a really messed up and unreadable code.
To solve this, we use Promise and Async/Await (.then()) in javascript.
getUser(function(user) {
getUserDetails(user.id, function(details) {
getUserPosts(user.id, function(posts) {
renderUserDashboard(user, details, posts, function() {
// More nested callbacks...
});
});
});
});
// Above code converts into below code
getUser()
.then(user => getUserDetails(user.id))
.then(details => getUserPosts(details.id))
.then(posts => renderUserDashboard(user, details, posts))
.catch(error => console.error(error));
Now, there’s a catch. You have to return output as a Promise
in getUser
function like this:
function getUser() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const user = { id: 1, name: "Alice" };
resolve(user); // Resolve the Promise with the user object
// If there is an error fetching data, you can reject the Promise like this:
// reject("Error: Unable to fetch user data");
}, 2000);
});
}
//or
async function getUser() {
await delay(); // Simulate a delay
return { id: 1, name: "Alice" }; // Return the user object
}
What are Higher order functions and First Class Functions in Javascript
To be conclusive, First class functions are the functions that are treated as variables, and they can also be passed as an arguments in another function.
const Person = {
play:(name) => {
return `Hey ${name} is playing`;
},
dance:(name) => {
return `${name} can dance`
},
walk:(name) => {
return `I am sure ${name} can walk `
},
}
While Higher order functions are the functions that take functions as their arguments or return function as result.
map
, filter
, reduce
are the example of higher order functions in javascript.
What are execution context and lexical environment in javascript?
Execution context is a collection of variable environments, scope chain, and this
keyword. Javascript code always runs inside an execution context, either global or functional.
Variable environment has all the variables including the function arguments. scope chain contains current variable environment and all its ancestor variable environments (enabling us to use the variables declared outside or in parent scope of a function).
Each time a function is called, an execution context is created and pushed in a call stack.
A Lexical environment has all the function and variable declarations along with the reference of outer lexical environment.
Differentiate between ==
and ===
==
is called loose equality while ===
is called strict equality. loose equality compares left and right values after coercing one of them to make both the same data-type, while strict equality compares them along with their data-types.
1 == '1' //true
1 === '1' //false
What are map
, filter
, find
, reduce
, forEach
, slice
and splice
operations?
map
: Its one of the higher order functions in javascript that returns a new array after performing an operation on it.filter
: Its another one of JavaScript’s higher order function that returns a new array which satisfy the condition provided in parameter function.find
: Same as filter but instead of returning an array of all passed elements, it just returns the first elementreduce
: Inside the parameter function of reduce, there are two things, accumulator and element. So that the element is applied to accumulator and finally the accumulator is returned.
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
// sum: 10
**forEach
** It just executes some operation for each elements on the same array.**slice
** : extracts and returns a section of array as a new array.
const numbers = [1, 2, 3, 4];
const slicedNumbers = numbers.slice(1, 3);
// slicedNumbers: [2, 3]
**splice**
: changes the contents of an array by removing or replacing existing elements and/or adding new elements.
const fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2, 0, "Lemon", "Kiwi"); //Banana,Orange,Lemon,Kiwi,Apple,Mango
fruits.splice(2, 2, "Lemon", "Kiwi"); //Banana,Orange,Lemon,Kiwi
//splice(startIndex, noOfItemsToRemove, {...newItems})
Explain Scope (global, functional, block) and Scope Chaining
Scope is a boundary that decides the accessibility and usability of a variable in a program. There are three scopes in javascript. Global, Functional and Block.
Scope Chaining:
let x = 99
function runThis() {
let x = 666
if (true) {
let x = true
console.log(x) //true
}
}
function runThis() {
let x = 666
if (true) {
console.log(x) //666
}
}
function runThis() {
if (true) {
console.log(x) //99
}
}
As we can see, JS engine searches for x firstly in current scope (here block scope), then the parent scope (here functional scope) until the global scope.
This chain like search behavior is called scope chaining in JavaScript.
Async JS, Event Loops, Callback Queue, Call Stack
Javascript is a synchronous language (single threaded) to be exact and it does execute process one at a time, but using methods like callbacks, async await and promise it does seem like things are being handled in parallel.
Example :
console.log('one')
setTimeout(() => {
console.log('two')
}, 3000)
console.log('three')
Event Loop is like a watcher who checks if callback queue has some change. If there is some function in it, it just transfers the topmost one to the call stack. So in above example firstly one
gets printed, then browser starts a 3s timer. Currently there is nothing in callback queue because timer hasn’t finished yet. So Javascript proceeds with executing next line and hence ‘three’ is logged.
After timer is finished callback from SetTimeOut is sent in callback queue and immediately detected by event loop and finally logs ‘two’.
Promise usage, Promise.all, Promise.race
In javascript, usually the engine doesn’t wait for a function or a task to execute because of event-loop, but we can make it so by using Promise. Promise is a function (constructor) that takes a callback with arguments resolve
, reject
.
Example:
const timerFunction = () => {
return new Promise((resolve, reject) => {
// Here we call resolve when our operation finishes.
setTimeOut(() => resolve('some output'), 3000)
// Simillarly when we want to throw error, we simply call reject.
})
}
const final = timerFunction() //Promise Object
In above example in the output we have a Promise object which has some prototype keys like then, and catch. We use these to run a callback when resolve triggers in original function (here timerFunction
) and when the original function triggers reject, respectively.
So when we use the above function like this,
final.then((res) => console.log(res)) // 'some output'
//or
async function getTimerPromise () {
try{
const res = await timerFunction
console.log(res)
}
catch(err){
console.log(err)
}
}
getTimerPromise() // 'some output'
then has a callback function with resolve message as the argument. We could have used .catch
for the case of error that could have been thrown by the original function.
finally
is triggered when the original function is completed and removed from the call stack. Its like the last callback of a function’s life cycle.
- Promise.all : all() is a static function that is created by javascript to take an array of promises and return a different array with fulfilled results. Mostly it is used to run API calls in non blocking behavior.
- Promise.race: It takes the same argument, an array of promises but like the name suggests, there is a race and the fastest one is returned. It returns a single value
Example:
const PromiseOne = () => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise One executed after 3 sec'), 3000)
})
}
const PromiseTwo = () => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise Two executed after 5 sec'), 5000)
})
}
Promise.all([PromiseOne(), PromiseTwo()]).then((res) => {
console.log(res) // (2) ['Promise One executed after 3 sec', 'Promise Two executed after 5 sec']
)}
Promise.race([PromiseOne(), PromiseTwo()]).then((res) => {
console.log(res) // Promise One executed after 3 sec
)}