Welcome to your JavaScript problem sets! These exercises are designed to help you practice real-world coding skills that you'll use as a software developer. Each problem focuses on a specific skill, like validating user input or handling API data, and is solvable in about 20 minutes. You'll get a clear explanation, starter code, and test cases to check your work. Let's dive in and start building!
When users fill out forms on a website (like signing up for an account), their input can be messy—extra spaces, weird characters, or even malicious code like <script> tags. As a developer, you need to clean and validate this input to keep your app safe and functional.
Write a function sanitizeUserInput that cleans up a user input string for a registration form. Your function should:
- Remove leading and trailing spaces (trim the string).
- Remove any HTML tags (like
<script>or<div>) to prevent security issues. - Ensure the final string is between 3 and 20 characters long.
- Return the cleaned string, or throw an error if the input is invalid (too short, too long, null, or undefined).
- Input: A string
input(e.g., " John<script> ", "Alice ", "a"). - Output: The cleaned string, or throw an error with a clear message.
- Constraints:
- Input string length: 0 to 50 characters.
- Throw an error if the cleaned string is less than 3 or more than 20 characters.
- Handle null or undefined inputs by throwing an error.
function sanitizeUserInput(input) {
// Your code here
}console.log(sanitizeUserInput(" John<script> ")); // Should return "John"
console.log(sanitizeUserInput(" Alice ")); // Should return "Alice"
try { sanitizeUserInput("a"); } catch (e) { console.log(e); } // Should throw "Input must be between 3 and 20 characters"
try { sanitizeUserInput(null); } catch (e) { console.log(e); } // Should throw "Input cannot be null or undefined"Web apps often fetch data from APIs, like user profiles from a server. This data comes as JSON, and you need to extract and filter the useful parts, like valid email addresses, to display in your app.
Write a function parseUserData that processes an array of user objects from an API. Each object has name, email, and other fields. Your function should:
- Extract only the
nameandemailfields. - Filter out users with invalid emails (emails must have "@" and end with ".com", ".org", or ".net").
- Return an array of objects with just
nameandemail.
- Input: An array of user objects, e.g.,
[{ name: "John", email: "[email protected]", id: 1 }, { name: "Jane", email: "invalid", id: 2 }]. - Output: An array of objects with valid emails, e.g.,
[{ name: "John", email: "[email protected]" }]. - Constraints:
- Input array length: 0 to 100.
- Skip users with missing or invalid emails.
- Valid emails have "@" and end with ".com", ".org", or ".net".
function parseUserData(users) {
// Your code here
}console.log(parseUserData([
{ name: "John", email: "[email protected]", id: 1 },
{ name: "Jane", email: "invalid", id: 2 }
])); // Should return [{ name: "John", email: "john@example.com" }]
console.log(parseUserData([])); // Should return []
console.log(parseUserData([
{ name: "Alice", email: "[email protected]" },
{ name: "Bob", email: "[email protected]" }
])); // Should return [{ name: "Alice", email: "alice@example.org" }, { name: "Bob", email: "bob@example.net" }]Apps like social media platforms limit how often users can perform actions (e.g., sending messages) to prevent spam. A rate limiter tracks actions over time and blocks users who do too much too fast.
Write a function rateLimiter that simulates a rate limiter. It tracks actions for each user and allows only 3 actions in a 5-second window. The function takes a user ID and a timestamp (in seconds) and returns true if the action is allowed, false if it’s blocked.
- Input: A user ID (
userId, string) and a timestamp (timestamp, number in seconds). - Output: A boolean (
trueif allowed,falseif blocked). - Constraints:
- User IDs: strings, 1 to 10 characters.
- Timestamps: non-negative integers.
- Allow up to 3 actions per user in a 5-second window.
function rateLimiter(userId, timestamp) {
// Your code here
}console.log(rateLimiter("user1", 1)); // true
console.log(rateLimiter("user1", 2)); // true
console.log(rateLimiter("user1", 3)); // true
console.log(rateLimiter("user1", 4)); // false
console.log(rateLimiter("user1", 7)); // true
console.log(rateLimiter("user2", 1)); // trueIn web apps, some calculations (like resizing images) are expensive. Caching results for the same inputs saves time and makes your app faster.
Write a function memoize that wraps a given function (like one that squares a number) to cache its results. If the same input is provided again, return the cached result instead of recomputing.
- Input: A function
fn(e.g.,x => x * x) and a numeric inputx. - Output: The result of
fn(x), using the cache if available. - Constraints:
- Input
x: integer, -100 to 100. - Cache persists across calls.
- Input
function memoize(fn) {
// Your code here
}const square = x => x * x;
const memoizedSquare = memoize(square);
console.log(memoizedSquare(5)); // 25 (computes)
console.log(memoizedSquare(5)); // 25 (from cache)
console.log(memoizedSquare(3)); // 9 (computes)
console.log(memoizedSquare(3)); // 9 (from cache)