Mastering Frontend Concepts: A Guide to Top Interview Questions
Introduction
Frontend interviews often include JavaScript challenges to evaluate problem-solving skills, deep understanding of core concepts, and ability to write maintainable code. This guide covers frequently asked questions from top tech companies like Flipkart, Meta, Google, Amazon, and others.
Topics Covered
1. Debouncing
Debouncing ensures a function is executed only after a specified delay has passed since the last time it was invoked.
function debounce(func, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
// Example Usage:
const log = debounce(() => console.log("Debounced!"), 300);
log(); // Executes after 300ms if no new calls
2. Throttling
Throttling ensures a function is executed at most once in a given time interval.
function throttle(func, wait) {
let lastCall = 0;
return function (...args) {
const now = Date.now();
if (now - lastCall >= wait) {
lastCall = now;
func.apply(this, args);
}
};
}
// Example Usage:
const log = throttle(() => console.log("Throttled!"), 1000);
log(); // Executes immediately, ignores further calls within 1 second
3. Currying
Currying transforms a function into a sequence of functions, each taking a single argument.
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn(...args);
}
return (...nextArgs) => curried(...args, ...nextArgs);
};
}
// Example Usage:
const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // Output: 6
4. Custom Promises
Implementing a basic Promise-like structure.
class CustomPromise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.callbacks = [];
const resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
this.callbacks.forEach((cb) => cb());
}
};
executor(resolve);
} then(onFulfilled) {
return new CustomPromise((resolve) => {
const handle = () => {
const result = onFulfilled(this.value);
resolve(result);
};
if (this.state === "fulfilled") {
handle();
} else {
this.callbacks.push(handle);
}
});
}
}// Example Usage:
new CustomPromise((resolve) => resolve(42))
.then((value) => value + 1)
.then(console.log); // Output: 43
5. Deep Flatten
Flattening a nested array up to a given depth.
function deepFlatten(arr, depth = Infinity) {
return depth > 0
? arr.reduce((flat, item) =>
flat.concat(Array.isArray(item) ? deepFlatten(item, depth - 1) : item), []
)
: arr.slice();
}
// Example Usage:
const nested = [1, [2, [3, [4, [5]]]]];
console.log(deepFlatten(nested, 4)); // Output: [1, 2, 3, 4, [5]]
6. Custom JSON.stringify
A custom implementation of JSON.stringify
.
function customStringify(obj) {
if (typeof obj !== "object" || obj === null) return String(obj);
if (Array.isArray(obj)) return `[${obj.map(customStringify).join(",")}]`;
return `{${Object.entries(obj)
.map(([key, value]) => `"${key}":${customStringify(value)}`)
.join(",")}}`;
}
// Example Usage:
const obj = { a: 1, b: { c: 2 } };
console.log(customStringify(obj)); // Output: {"a":1,"b":{"c":2}}
7. Event Emitter
A basic event emitter implementation.
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
if (!this.events[event]) this.events[event] = [];
this.events[event].push(listener);
}
emit(event, ...args) {
if (this.events[event]) {
this.events[event].forEach((listener) => listener(...args));
}
}
off(event, listener) {
if (!this.events[event]) return;
this.events[event] = this.events[event].filter((l) => l !== listener);
}
}
// Example Usage:
const emitter = new EventEmitter();
emitter.on("log", (msg) => console.log(msg));
emitter.emit("log", "Hello World!"); // Output: Hello World!
8. Lodash _.get
A simplified version of Lodash’s get
function.
function get(obj, path, defaultValue) {
return path.split(".").reduce((acc, key) => acc?.[key], obj) || defaultValue;
}
// Example Usage:
const data = { a: { b: { c: 42 } } };
console.log(get(data, "a.b.c", "default")); // Output: 42
console.log(get(data, "a.x.c", "default")); // Output: "default"
9. Deep Clone
A deep cloning function for objects.
function deepClone(obj) {
if (obj === null || typeof obj !== "object") return obj;
if (Array.isArray(obj)) return obj.map(deepClone);
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, deepClone(value)])
);
}
// Example Usage:
const obj = { a: { b: 2 }, c: [1, 2] };
const clone = deepClone(obj);
console.log(clone); // Output: { a: { b: 2 }, c: [1, 2] }
Summary
This guide addresses the most common frontend interview questions, consolidating concepts like debouncing, throttling, currying, and custom implementations of Promises, JSON.stringify, and more. By mastering these implementations, you’ll not only prepare for interviews but also gain a stronger understanding of JavaScript fundamentals.