Master JavaScript interviews with this comprehensive collection of 60 hand-picked coding problems, complete with solutions, time complexity analysis, and expert interview tips.
Are you preparing for a JavaScript developer interview and feeling overwhelmed by the endless list of potential coding questions? You're not alone. Whether you're applying for a frontend developer, full-stack engineer, or Node.js position, mastering JavaScript interview questions is crucial for landing your dream job.
This ultimate JavaScript coding interview cheat sheet is designed for developers who want to:
Unlike typical coding question lists, each problem in this guide includes:
This comprehensive guide covers 60 JavaScript interview problems across 8 categories:
Each solution is optimized for readability and interview performance. We prioritize code that's easy to explain under pressure while demonstrating your understanding of JavaScript fundamentals.
const reverseString = str => [...str].reverse().join('');
console.log(reverseString("hello")); // "olleh"
const isPalindrome = str => str === [...str].reverse().join('');
console.log(isPalindrome("racecar")); // true
console.log(isPalindrome("hello")); // false
const countVowels = str => (str.match(/[aeiou]/gi) || []).length;
console.log(countVowels("hello world")); // 3
const capitalize = str => str.charAt(0).toUpperCase() + str.slice(1);
console.log(capitalize("hello")); // "Hello"
const titleCase = str => str.split(' ').map(word =>
word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
).join(' ');
console.log(titleCase("hello world")); // "Hello World"
const removeDuplicates = str => [...new Set(str)].join('');
console.log(removeDuplicates("hello")); // "helo"
const longestWord = str => str.split(' ').reduce((longest, word) =>
word.length > longest.length ? word : longest, ''
);
console.log(longestWord("The quick brown fox")); // "quick"
const isAnagram = (str1, str2) => {
const normalize = str => str.toLowerCase().split('').sort().join('');
return normalize(str1) === normalize(str2);
};
console.log(isAnagram("listen", "silent")); // true
const removeDuplicates = arr => [...new Set(arr)];
console.log(removeDuplicates([1, 2, 2, 3, 4, 4])); // [1, 2, 3, 4]
const findMax = arr => Math.max(...arr);
console.log(findMax([1, 5, 3, 9, 2])); // 9
const sum = arr => arr.reduce((acc, num) => acc + num, 0);
console.log(sum([1, 2, 3, 4])); // 10
const flatten = arr => arr.flat(Infinity);
console.log(flatten([1, [2, [3, [4]]]])); // [1, 2, 3, 4]
// Recursive approach
const flattenRecursive = arr => arr.reduce((acc, val) =>
Array.isArray(val) ? acc.concat(flattenRecursive(val)) : acc.concat(val), []
);
const chunk = (arr, size) => {
const result = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
};
console.log(chunk([1, 2, 3, 4, 5], 2)); // [[1, 2], [3, 4], [5]]
const findMissing = arr => {
const n = arr.length + 1;
const expectedSum = (n * (n + 1)) / 2;
const actualSum = arr.reduce((a, b) => a + b, 0);
return expectedSum - actualSum;
};
console.log(findMissing([1, 2, 4, 5])); // 3
const rotate = (arr, k) => {
k = k % arr.length;
return [...arr.slice(-k), ...arr.slice(0, -k)];
};
console.log(rotate([1, 2, 3, 4, 5], 2)); // [4, 5, 1, 2, 3]
const twoSum = (arr, target) => {
const map = new Map();
for (let i = 0; i < arr.length; i++) {
const complement = target - arr[i];
if (map.has(complement)) return [map.get(complement), i];
map.set(arr[i], i);
}
return null;
};
console.log(twoSum([2, 7, 11, 15], 9)); // [0, 1]
const moveZeros = arr => {
const nonZeros = arr.filter(x => x !== 0);
const zeros = arr.filter(x => x === 0);
return [...nonZeros, ...zeros];
};
console.log(moveZeros([0, 1, 0, 3, 12])); // [1, 3, 12, 0, 0]
const intersection = (arr1, arr2) => [...new Set(arr1)].filter(x => arr2.includes(x));
console.log(intersection([1, 2, 3], [2, 3, 4])); // [2, 3]
const fibonacci = n => {
if (n <= 1) return n;
let a = 0, b = 1;
for (let i = 2; i <= n; i++) {
[a, b] = [b, a + b];
}
return b;
};
console.log(fibonacci(7)); // 13
const isPrime = num => {
if (num <= 1) return false;
for (let i = 2; i <= Math.sqrt(num); i++) {
if (num % i === 0) return false;
}
return true;
};
console.log(isPrime(17)); // true
const factorial = n => n <= 1 ? 1 : n * factorial(n - 1);
console.log(factorial(5)); // 120
// Iterative
const factorialIterative = n => {
let result = 1;
for (let i = 2; i <= n; i++) result *= i;
return result;
};
const reverseNumber = num => parseInt([...String(Math.abs(num))].reverse().join('')) * Math.sign(num);
console.log(reverseNumber(12345)); // 54321
console.log(reverseNumber(-123)); // -321
const countDigits = num => String(Math.abs(num)).length;
console.log(countDigits(12345)); // 5
const deepClone = obj => JSON.parse(JSON.stringify(obj));
console.log(deepClone({a: 1, b: {c: 2}})); // {a: 1, b: {c: 2}}
// Better with structuredClone
const deepClone2 = obj => structuredClone(obj);
const merge = (obj1, obj2) => ({...obj1, ...obj2});
console.log(merge({a: 1}, {b: 2})); // {a: 1, b: 2}
// Deep merge
const deepMerge = (obj1, obj2) => {
const result = {...obj1};
for (let key in obj2) {
if (typeof obj2[key] === 'object' && !Array.isArray(obj2[key])) {
result[key] = deepMerge(result[key] || {}, obj2[key]);
} else {
result[key] = obj2[key];
}
}
return result;
};
const groupBy = (arr, key) => arr.reduce((acc, obj) => {
const group = obj[key];
acc[group] = acc[group] || [];
acc[group].push(obj);
return acc;
}, {});
const data = [{type: 'fruit', name: 'apple'}, {type: 'fruit', name: 'banana'}];
console.log(groupBy(data, 'type')); // {fruit: [{...}, {...}]}
const getNestedProperty = (obj, path) => path.split('.').reduce((acc, key) => acc?.[key], obj);
console.log(getNestedProperty({a: {b: {c: 42}}}, 'a.b.c')); // 42
const isEqual = (obj1, obj2) => JSON.stringify(obj1) === JSON.stringify(obj2);
console.log(isEqual({a: 1}, {a: 1})); // true
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
// Usage
await delay(1000);
console.log('After 1 second');
const retry = async (fn, retries = 3) => {
for (let i = 0; i < retries; i++) {
try {
return await fn();
} catch (err) {
if (i === retries - 1) throw err;
}
}
};
const promiseAll = promises => {
return new Promise((resolve, reject) => {
const results = [];
let completed = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise).then(value => {
results[index] = value;
completed++;
if (completed === promises.length) resolve(results);
}).catch(reject);
});
});
};
const debounce = (fn, delay) => {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
};
// Usage
const debouncedSearch = debounce(() => console.log('Searching...'), 300);
const throttle = (fn, delay) => {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
fn.apply(this, args);
}
};
};
// Usage
const throttledScroll = throttle(() => console.log('Scrolling...'), 200);
// Parallel - faster
const parallel = async () => {
const [result1, result2] = await Promise.all([
fetch('/api/1'),
fetch('/api/2')
]);
};
// Sequential - slower but dependent
const sequential = async () => {
const result1 = await fetch('/api/1');
const result2 = await fetch('/api/2');
};
const binarySearch = (arr, target) => {
let left = 0, right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) return mid;
if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
};
console.log(binarySearch([1, 2, 3, 4, 5], 3)); // 2
const bubbleSort = arr => {
const n = arr.length;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
};
console.log(bubbleSort([5, 3, 8, 4, 2])); // [2, 3, 4, 5, 8]
const quickSort = arr => {
if (arr.length <= 1) return arr;
const pivot = arr[arr.length - 1];
const left = arr.filter((x, i) => x <= pivot && i < arr.length - 1);
const right = arr.filter(x => x > pivot);
return [...quickSort(left), pivot, ...quickSort(right)];
};
console.log(quickSort([5, 3, 8, 4, 2])); // [2, 3, 4, 5, 8]
const findUnique = arr => arr.filter((val, idx) => arr.indexOf(val) === idx);
console.log(findUnique([1, 2, 2, 3, 4, 4])); // [1, 2, 3, 4]
const mostFrequent = arr => {
const freq = {};
let maxCount = 0, result = null;
arr.forEach(val => {
freq[val] = (freq[val] || 0) + 1;
if (freq[val] > maxCount) {
maxCount = freq[val];
result = val;
}
});
return result;
};
console.log(mostFrequent([1, 3, 2, 3, 3, 1])); // 3
const isValidParentheses = str => {
const stack = [];
const pairs = {'(': ')', '[': ']', '{': '}'};
for (let char of str) {
if (pairs[char]) {
stack.push(char);
} else {
const last = stack.pop();
if (pairs[last] !== char) return false;
}
}
return stack.length === 0;
};
console.log(isValidParentheses("({[]})")); // true
const generateUUID = () => {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};
console.log(generateUUID()); // "a3f2b4c5-..."
const parseQueryString = url => {
const params = new URLSearchParams(url.split('?')[1]);
return Object.fromEntries(params);
};
console.log(parseQueryString('https://site.com?name=john&age=30'));
// {name: 'john', age: '30'}
const parseCookies = () => {
return document.cookie.split(';').reduce((acc, cookie) => {
const [key, value] = cookie.trim().split('=');
acc[key] = decodeURIComponent(value);
return acc;
}, {});
};
const storage = {
set: (key, value) => localStorage.setItem(key, JSON.stringify(value)),
get: key => JSON.parse(localStorage.getItem(key)),
remove: key => localStorage.removeItem(key),
clear: () => localStorage.clear()
};
const formatNumber = num => num.toLocaleString('en-US');
console.log(formatNumber(1234567)); // "1,234,567"
// Manual
const formatManual = num => num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
const truncate = (str, length) => str.length > length ? str.slice(0, length) + '...' : str;
console.log(truncate("Hello World", 8)); // "Hello Wo..."
const randomColor = () => '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
console.log(randomColor()); // "#a3f2b4"
const getAge = birthday => {
const today = new Date();
const birth = new Date(birthday);
let age = today.getFullYear() - birth.getFullYear();
const monthDiff = today.getMonth() - birth.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) age--;
return age;
};
console.log(getAge('1990-05-15')); // 35 (as of 2025)
const shuffle = arr => {
const result = [...arr];
for (let i = result.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[result[i], result[j]] = [result[j], result[i]];
}
return result;
};
console.log(shuffle([1, 2, 3, 4, 5]));
const memoize = fn => {
const cache = {};
return (...args) => {
const key = JSON.stringify(args);
if (key in cache) return cache[key];
cache[key] = fn(...args);
return cache[key];
};
};
const slowFib = n => n <= 1 ? n : slowFib(n - 1) + slowFib(n - 2);
const fastFib = memoize(slowFib);
console.log(fastFib(40)); // Much faster!
// 51. Remove falsy values
const compact = arr => arr.filter(Boolean);
// 52. Get unique by property
const uniqueBy = (arr, key) => [...new Map(arr.map(x => [x[key], x])).values()];
// 53. Pick object properties
const pick = (obj, keys) => Object.fromEntries(keys.map(k => [k, obj[k]]));
// 54. Omit object properties
const omit = (obj, keys) => Object.fromEntries(Object.entries(obj).filter(([k]) => !keys.includes(k)));
// 55. Sleep function
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
// 56. Random integer in range
const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
// 57. Check if empty object
const isEmpty = obj => Object.keys(obj).length === 0;
// 58. Clamp number
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
// 59. Average of array
const average = arr => arr.reduce((a, b) => a + b, 0) / arr.length;
// 60. Range array
const range = (start, end) => Array.from({length: end - start + 1}, (_, i) => start + i);
| Problem Type | Best Approach | Time Complexity |
|---|---|---|
| Search sorted | Binary search | O(log n) |
| Search unsorted | Linear/Hash | O(n) or O(1) |
| Sort | Quick/Merge sort | O(n log n) |
| Duplicates | Set/Hash map | O(n) |
| Two pointer | Array problems | O(n) |
| Stack | Parentheses/undo | O(n) |
| Recursion | Tree/divide-conquer | Varies |
| DP/Memo | Optimization | O(n) space |
Practice these problems, understand the patterns, and you'll be ready to ace any JavaScript coding interview.
Related Keywords: JavaScript interview questions, coding interview preparation, frontend developer interview, JavaScript algorithms, web developer coding test, technical interview questions, JavaScript programming challenges, ES6 interview questions, coding patterns JavaScript, algorithm interview prep, JavaScript developer jobs 2025