Jump to Your Level
- Junior Developer (Challenges 1-10)
- Mid-Level Developer (Challenges 11-20)
- Senior Developer (Challenges 21-30)
Junior Developer Challenges
Challenge 1: Variable Declaration and Basic Operations
Create variables to store your name, age, and favorite programming language. Then create a sentence using these variables.
let name = 'John Doe';
let age = 25;
let favLanguage = 'JavaScript';
let introduction = `Hi, I'm ${name}, I'm ${age} years old and my favorite programming language is ${favLanguage}.`;
console.log(introduction);
Challenge 2: Simple Function
Write a function that takes two numbers as parameters and returns their sum.
function addNumbers(a, b) {
return a + b;
}
console.log(addNumbers(5, 3)); // Output: 8
Challenge 3: Array Basics
Create an array of fruits and use a for loop to print each fruit with its index.
let fruits = ['apple', 'banana', 'orange', 'grape'];
for (let i = 0; i < fruits.length; i++) {
console.log(`${i}: ${fruits[i]}`);
}
Challenge 4: Conditional Statements
Write a function that determines if a number is positive, negative, or zero.
function checkNumber(num) {
if (num > 0) {
return 'positive';
} else if (num < 0) {
return 'negative';
} else {
return 'zero';
}
}
console.log(checkNumber(5)); // positive
console.log(checkNumber(-3)); // negative
console.log(checkNumber(0)); // zero
Challenge 5: String Manipulation
Create a function that reverses a string without using the built-in reverse method.
function reverseString(str) {
let reversed = '';
for (let i = str.length - 1; i >= 0; i--) {
reversed += str[i];
}
return reversed;
}
console.log(reverseString('hello')); // Output: 'olleh'
Challenge 6: Object Basics
Create a person object with properties for name, age, and city. Add a method that returns a greeting.
let person = {
name: 'Alice',
age: 30,
city: 'New York',
greet: function() {
return `Hello, I'm ${this.name} from ${this.city}`;
}
};
console.log(person.greet());
Challenge 7: Find Maximum
Write a function that finds the largest number in an array.
function findMax(numbers) {
let max = numbers[0];
for (let i = 1; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
return max;
}
console.log(findMax([3, 7, 2, 9, 1])); // Output: 9
Challenge 8: Even or Odd
Create a function that checks if a number is even or odd.
function isEven(number) {
return number % 2 === 0;
}
console.log(isEven(4)); // true
console.log(isEven(7)); // false
Challenge 9: Count Characters
Write a function that counts the number of characters in a string (excluding spaces).
function countCharacters(str) {
let count = 0;
for (let i = 0; i < str.length; i++) {
if (str[i] !== ' ') {
count++;
}
}
return count;
}
console.log(countCharacters('hello world')); // Output: 10
Challenge 10: Simple Calculator
Create a calculator function that performs basic operations (add, subtract, multiply, divide).
function calculator(num1, num2, operation) {
switch (operation) {
case 'add':
return num1 + num2;
case 'subtract':
return num1 - num2;
case 'multiply':
return num1 * num2;
case 'divide':
return num2 !== 0 ? num1 / num2 : 'Cannot divide by zero';
default:
return 'Invalid operation';
}
}
console.log(calculator(10, 5, 'add')); // 15
console.log(calculator(10, 5, 'divide')); // 2
Mid-Level Developer Challenges
Challenge 11: Array Methods
Use array methods to filter, map, and reduce. Find all even numbers, double them, and sum the results.
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let result = numbers
.filter(num => num % 2 === 0)
.map(num => num * 2)
.reduce((sum, num) => sum + num, 0);
console.log(result); // Output: 60
Challenge 12: Closures
Create a function that uses closure to create a counter.
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
let counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
Challenge 13: Object Destructuring
Use destructuring to extract values from objects and arrays.
let user = {
name: 'John',
age: 30,
address: {
city: 'Boston',
zipCode: '02101'
}
};
// Object destructuring
let { name, age, address: { city } } = user;
console.log(`${name}, ${age}, ${city}`);
// Array destructuring
let colors = ['red', 'green', 'blue'];
let [first, second, third] = colors;
console.log(first, second, third);
Challenge 14: Arrow Functions and This
Demonstrate the difference between arrow functions and regular functions with ‘this’ binding.
let obj = {
name: 'Test Object',
regularFunction: function() {
console.log('Regular function:', this.name);
},
arrowFunction: () => {
console.log('Arrow function:', this.name);
},
nestedExample: function() {
setTimeout(() => {
console.log('Arrow in setTimeout:', this.name);
}, 100);
}
};
obj.regularFunction(); // 'Test Object'
obj.arrowFunction(); // undefined
obj.nestedExample(); // 'Test Object'
Challenge 15: Promise Basics
Create a function that returns a Promise and handle it with .then() and .catch().
function fetchData(shouldSucceed) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldSucceed) {
resolve('Data fetched successfully!');
} else {
reject('Error: Failed to fetch data');
}
}, 1000);
});
}
fetchData(true)
.then(data => console.log(data))
.catch(error => console.log(error));
Challenge 16: Set and Map
Use Set to remove duplicates from an array and Map to store key-value pairs.
// Using Set to remove duplicates
let numbers = [1, 2, 2, 3, 4, 4, 5];
let uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers); // [1, 2, 3, 4, 5]
// Using Map for key-value storage
let userRoles = new Map();
userRoles.set('john', 'admin');
userRoles.set('jane', 'user');
userRoles.set('bob', 'moderator');
console.log(userRoles.get('john')); // 'admin'
console.log(userRoles.has('jane')); // true
Challenge 17: Classes and Inheritance
Create a class hierarchy with inheritance and method overriding.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() {
console.log(`${this.name} barks`);
}
getInfo() {
return `${this.name} is a ${this.breed}`;
}
}
let dog = new Dog('Buddy', 'Golden Retriever');
dog.speak(); // 'Buddy barks'
console.log(dog.getInfo()); // 'Buddy is a Golden Retriever'
Challenge 18: Async/Await
Convert Promise-based code to use async/await syntax.
async function fetchUserData(userId) {
try {
let response = await fetch(`/api/users/${userId}`);
let userData = await response.json();
return userData;
} catch (error) {
console.error('Error fetching user data:', error);
throw error;
}
}
// Usage
async function displayUser() {
try {
let user = await fetchUserData(123);
console.log(user);
} catch (error) {
console.log('Failed to display user');
}
}
Challenge 19: Regular Expressions
Use regex to validate email addresses and extract information from strings.
function validateEmail(email) {
let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
function extractPhoneNumbers(text) {
let phoneRegex = /\b\d{3}-\d{3}-\d{4}\b/g;
return text.match(phoneRegex) || [];
}
console.log(validateEmail('[email protected]')); // true
console.log(extractPhoneNumbers('Call me at 123-456-7890 or 987-654-3210'));
Challenge 20: Module Pattern
Create a module using the revealing module pattern to encapsulate functionality.
let Calculator = (function() {
let result = 0;
function add(x) {
result += x;
return this;
}
function subtract(x) {
result -= x;
return this;
}
function multiply(x) {
result *= x;
return this;
}
function getResult() {
return result;
}
function reset() {
result = 0;
return this;
}
return {
add: add,
subtract: subtract,
multiply: multiply,
getResult: getResult,
reset: reset
};
})();
// Usage
let finalResult = Calculator
.add(10)
.multiply(2)
.subtract(5)
.getResult();
console.log(finalResult); // 15
Senior Developer Challenges
Challenge 21: Deep Cloning
Implement a function that creates a deep clone of an object, handling nested objects and arrays.
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (obj instanceof Date) {
return new Date(obj.getTime());
}
if (obj instanceof Array) {
return obj.map(item => deepClone(item));
}
if (typeof obj === 'object') {
let clonedObj = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clonedObj[key] = deepClone(obj[key]);
}
}
return clonedObj;
}
}
let original = {
name: 'John',
details: {
age: 30,
hobbies: ['reading', 'coding']
}
};
let cloned = deepClone(original);
cloned.details.age = 25;
console.log(original.details.age); // Still 30
Challenge 22: Debounce Function
Implement a debounce function that delays function execution until after a specified time has elapsed.
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
// Usage example
let searchInput = document.getElementById('search');
let debouncedSearch = debounce(function(event) {
console.log('Searching for:', event.target.value);
// Perform search API call
}, 300);
searchInput.addEventListener('input', debouncedSearch);
Challenge 23: Custom Event Emitter
Create an EventEmitter class that can register listeners and emit events.
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.apply(this, args);
});
}
}
off(event, listenerToRemove) {
if (this.events[event]) {
this.events[event] = this.events[event].filter(
listener => listener !== listenerToRemove
);
}
}
}
// Usage
let emitter = new EventEmitter();
emitter.on('userLogin', (username) => {
console.log(`${username} logged in`);
});
emitter.emit('userLogin', 'john_doe');
Challenge 24: Memoization
Implement a memoization function to cache expensive function results.
function memoize(fn) {
let cache = new Map();
return function(...args) {
let key = JSON.stringify(args);
if (cache.has(key)) {
console.log('Cache hit!');
return cache.get(key);
}
console.log('Computing result...');
let result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
// Expensive fibonacci function
let fibonacci = memoize(function(n) {
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
});
console.log(fibonacci(40)); // Will be much faster with memoization
Challenge 25: Custom Promise Implementation
Implement a basic Promise class from scratch.
class CustomPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(callback => callback(value));
}
};
let reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.value = reason;
this.onRejectedCallbacks.forEach(callback => callback(reason));
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled && onFulfilled(this.value);
} else if (this.state === 'rejected') {
onRejected && onRejected(this.value);
} else {
onFulfilled && this.onFulfilledCallbacks.push(onFulfilled);
onRejected && this.onRejectedCallbacks.push(onRejected);
}
}
}
Challenge 26: Functional Programming Utilities
Implement functional programming utilities: curry, compose, and pipe.
// Curry function
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...nextArgs) {
return curried.apply(this, args.concat(nextArgs));
};
}
};
}
// Compose function (right to left)
function compose(...functions) {
return function(value) {
return functions.reduceRight((acc, fn) => fn(acc), value);
};
}
// Pipe function (left to right)
function pipe(...functions) {
return function(value) {
return functions.reduce((acc, fn) => fn(acc), value);
};
}
// Usage examples
let add = (a, b) => a + b;
let multiply = (a, b) => a * b;
let square = x => x * x;
let curriedAdd = curry(add);
let addFive = curriedAdd(5);
console.log(addFive(3)); // 8
let pipeline = pipe(
x => x + 1,
x => x * 2,
square
);
console.log(pipeline(3)); // 64
Challenge 27: Observer Pattern
Implement the Observer pattern for creating a publish-subscribe system.
class Subject {
constructor() {
this.observers = [];
this.state = {};
}
addObserver(observer) {
this.observers.push(observer);
}
removeObserver(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notifyObservers(data) {
this.observers.forEach(observer => {
observer.update(data);
});
}
setState(newState) {
this.state = { ...this.state, ...newState };
this.notifyObservers(this.state);
}
}
class Observer {
constructor(name) {
this.name = name;
}
update(data) {
console.log(`${this.name} received update:`, data);
}
}
// Usage
let subject = new Subject();
let observer1 = new Observer('Observer 1');
let observer2 = new Observer('Observer 2');
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.setState({ message: 'Hello World!' });
Challenge 28: Custom Iterator
Create a custom iterator for a data structure using Symbol.iterator.
class NumberRange {
constructor(start, end) {
this.start = start;
this.end = end;
}
[Symbol.iterator]() {
let current = this.start;
let end = this.end;
return {
next() {
if (current <= end) {
return { value: current++, done: false };
} else {
return { done: true };
}
}
};
}
}
// Usage
let range = new NumberRange(1, 5);
for (let num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
// Or using spread operator
console.log([...range]); // [1, 2, 3, 4, 5]
Challenge 29: Proxy for Object Validation
Use Proxy to create an object with validation and computed properties.
function createValidatedUser(initialData = {}) {
let data = { ...initialData };
return new Proxy(data, {
set(target, property, value) {
// Validation rules
if (property === 'email') {
let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
throw new Error('Invalid email format');
}
}
if (property === 'age') {
if (typeof value !== 'number' || value < 0 || value > 150) {
throw new Error('Age must be a number between 0 and 150');
}
}
target[property] = value;
return true;
},
get(target, property) {
// Computed properties
if (property === 'fullName') {
return `${target.firstName || ''} ${target.lastName || ''}`.trim();
}
if (property === 'isAdult') {
return (target.age || 0) >= 18;
}
return target[property];
}
});
}
// Usage
let user = createValidatedUser();
user.firstName = 'John';
user.lastName = 'Doe';
user.age = 25;
user.email = '[email protected]';
console.log(user.fullName); // 'John Doe'
console.log(user.isAdult); // true
Challenge 30: Performance Optimization with Web Workers
Demonstrate how to use Web Workers for CPU-intensive tasks without blocking the main thread.
// Main thread code
function runExpensiveCalculation(data) {
return new Promise((resolve, reject) => {
// Create a Web Worker
let worker = new Worker('calculation-worker.js');
worker.postMessage(data);
worker.onmessage = function(event) {
resolve(event.data);
worker.terminate();
};
worker.onerror = function(error) {
reject(error);
worker.terminate();
};
});
}
// calculation-worker.js (separate file)
/*
self.onmessage = function(event) {
let data = event.data;
// Simulate expensive calculation
let result = 0;
for (let i = 0; i < data.iterations; i++) {
result += Math.random() * Math.sin(i) * Math.cos(i);
}
// Send result back to main thread
self.postMessage({
result: result,
message: 'Calculation completed'
});
};
*/
// Usage in main thread
async function performCalculation() {
try {
console.log('Starting calculation...');
let result = await runExpensiveCalculation({ iterations: 1000000 });
console.log('Calculation result:', result);
} catch (error) {
console.error('Calculation failed:', error);
}
}


