Master JavaScript through hands-on coding challenges with automated tests.
- Node.js (v16 or higher)
- npm
npm install# Run all tests
npm test
# Run tests for a specific assignment
npm run test:01 # Deep Clone
npm run test:02 # Debounce/Throttle
# ... etc
# Run tests in watch mode
npm test:watch
# Run with coverage report
npm test:coverage01 - Deep Clone
Difficulty: Medium | Topics: Recursion, Type checking, WeakMap
Create a deep copy of any JavaScript value including nested objects, arrays, and special types (Date, RegExp, Map, Set). Learn to handle circular references using WeakMap and understand JavaScript's type system.
02 - Debounce & Throttle
Difficulty: Medium | Topics: Closures, Timing, this context
Implement two essential rate-limiting utilities. Debounce delays execution until after a pause in calls; throttle limits execution to once per time period. Master closures, setTimeout, and preserving execution context.
03 - Custom Bind
Difficulty: Hard | Topics: this context, Prototypes, new operator
Recreate Function.prototype.bind from scratch. Deep dive into how this binding works, handle partial application of arguments, and support constructor invocation with the new keyword.
04 - Memoization
Difficulty: Medium | Topics: Closures, Caching, Higher-order functions
Build a memoization utility that caches function results based on arguments. Implement advanced features like TTL (time-to-live), max cache size with LRU eviction, and custom key generation.
05 - Promise Utilities
Difficulty: Hard | Topics: Promises, Async control flow, Error handling
Implement Promise.all, Promise.race, Promise.allSettled, and Promise.any from scratch. Understand how promises work internally and learn to coordinate multiple async operations.
06 - Async Queue
Difficulty: Hard | Topics: Concurrency control, Promises, Task scheduling
Build an async task queue with configurable concurrency limits. Learn to manage parallel execution, handle task priorities, implement pause/resume functionality, and track queue state.
07 - Retry with Backoff
Difficulty: Medium | Topics: Error handling, Async/await, Algorithms
Create a retry utility with exponential backoff for handling transient failures. Implement different backoff strategies (fixed, linear, exponential), jitter for thundering herd prevention, and configurable retry conditions.
08 - Event Emitter
Difficulty: Medium | Topics: Pub/Sub pattern, Callbacks, Memory management
Implement a Node.js-style EventEmitter with on, off, emit, and once methods. Learn the publish-subscribe pattern, manage listener lifecycles, and handle edge cases like removing listeners during emit.
09 - Observable
Difficulty: Hard | Topics: Reactive programming, Functional composition, Streams
Create a simple Observable implementation with operators like map, filter, take, and skip. Understand reactive data streams, lazy evaluation, and the observer pattern used in RxJS.
10 - LRU Cache
Difficulty: Hard | Topics: Data structures, Map ordering, Cache algorithms
Build a Least Recently Used cache that evicts the oldest items when at capacity. Learn to leverage Map's insertion order, implement O(1) operations, and understand cache eviction strategies.
11 - Singleton
Difficulty: Easy | Topics: Creational patterns, Static methods, Closures
Implement the singleton pattern ensuring only one instance exists. Create both class-based and factory-based singletons, understand lazy initialization, and learn when singletons are appropriate.
12 - Factory Pattern
Difficulty: Medium | Topics: Creational patterns, Dynamic instantiation, Validation
Build a factory with type registration and validation. Learn to decouple object creation from usage, implement extensible factories, and validate constructor arguments dynamically.
13 - Decorator Pattern
Difficulty: Medium | Topics: Higher-order functions, Function composition, AOP
Create function decorators for logging, timing, retry, memoization, and validation. Learn aspect-oriented programming concepts, implement compose and pipe utilities, and understand how decorators wrap behavior.
14 - Middleware Pipeline
Difficulty: Hard | Topics: Chain of responsibility, Async middleware, Express/Koa patterns
Build an Express/Koa-style middleware pipeline. Understand how middleware chains work, implement the next() pattern, handle async middleware, and compose middleware functions.
15 - Dependency Injection
Difficulty: Hard | Topics: IoC container, SOLID principles, Circular dependency detection
Create a DI container supporting class registration, factory functions, singletons, and dependency resolution. Learn inversion of control, detect circular dependencies, and understand how frameworks like Angular manage dependencies.
16 - State Machine
Difficulty: Hard | Topics: FSM, State management, Guard conditions
Implement a finite state machine with states, transitions, guards, and actions. Learn to model complex workflows, validate state transitions, and manage application state predictably.
17 - Command Pattern
Difficulty: Medium | Topics: Undo/Redo, Action encapsulation, History management
Build a command system with undo/redo support. Encapsulate operations as objects, implement command history, create macro commands, and learn how text editors handle reversible actions.
18 - Strategy Pattern
Difficulty: Medium | Topics: Interchangeable algorithms, Runtime behavior selection
Implement the strategy pattern for sorting algorithms, pricing calculations, and validation rules. Learn to swap algorithms at runtime, reduce conditional logic, and follow the open/closed principle.
19 - Proxy Pattern
Difficulty: Medium | Topics: ES6 Proxy, Metaprogramming, Access control
Create proxies for validation, logging, caching, access control, lazy loading, and change observation. Master the ES6 Proxy API, implement traps for property access, and understand metaprogramming concepts.
20 - Builder Pattern
Difficulty: Medium | Topics: Fluent interfaces, Object construction, Method chaining
Build fluent builders for SQL queries, HTML elements, configuration objects, and HTTP requests. Learn to construct complex objects step-by-step, implement method chaining, and separate construction from representation.
- Click the Fork button at the top right of this repository
- This creates your own copy of the repository under your GitHub account
- Clone your forked repository to your local machine:
git clone https://github.com/YOUR_USERNAME/js-workshop.git cd js-workshop npm install
Create a new branch for each assignment you work on:
git checkout -b assignment-01-deep-cloneUse this naming convention: assignment-XX-name (e.g., assignment-01-deep-clone, assignment-05-promise-utilities)
- Open the assignment folder (e.g.,
01-deep-clone/) - Read the
README.mdfor requirements and hints - Implement your solution in
index.js(look for TODO comments) - Run tests frequently to check your progress:
npm run test:01
Once all tests pass, commit your work:
git add .
git commit -m "Complete assignment 01: Deep Clone"-
Push your branch to your fork:
git push origin assignment-01-deep-clone
-
Go to your fork on GitHub
-
Click "Compare & pull request" button (or go to Pull Requests → New Pull Request)
-
Set the PR details:
- Base repository: The original repository (instructor's repo)
- Base branch:
main - Head repository: Your fork
- Compare branch: Your assignment branch (e.g.,
assignment-01-deep-clone)
-
Fill in the PR template:
## Assignment: 01 - Deep Clone ### Checklist - [ ] All tests pass (`npm run test:01`) - [ ] Code follows the existing style - [ ] No modifications to test files ### Notes (Any questions or comments about your implementation)
-
Click "Create Pull Request"
-
Your instructor will review your PR and may leave comments
-
To make changes based on feedback:
# Make sure you're on your assignment branch git checkout assignment-01-deep-clone # Make your changes, then commit git add . git commit -m "Address review feedback" # Push the changes (PR updates automatically) git push origin assignment-01-deep-clone
-
Once approved, your PR will be merged
You can work on multiple assignments in parallel:
# Start assignment 2 while waiting for assignment 1 review
git checkout main
git pull origin main
git checkout -b assignment-02-debounce-throttleIf the main repository is updated:
# Add the original repo as upstream (one time only)
git remote add upstream https://github.com/ORIGINAL_OWNER/js-workshop.git
# Fetch and merge updates
git checkout main
git fetch upstream
git merge upstream/main
git push origin mainEach assignment folder contains:
README.md- Assignment description and requirementsindex.js- Starter code with TODO markersindex.test.js- Jest tests to verify your solution
- Read the README carefully before starting
- Run the tests first to see what's expected
- Implement incrementally - get one test passing at a time
- Check edge cases - tests cover many scenarios
- Don't modify test files - only edit
index.js
MIT