Advanced JavaScript Exercises (Part 6)
Lesson Objective:
These exercises dive deeper into more advanced JavaScript concepts and coding challenges without the use of external libraries or frameworks. The goal is to continue building proficiency in JavaScript with topics such as recursion, browser storage, animations, algorithms, and custom form validation.
Learning Outcomes:
- Implement recursive solutions for common problems.
- Use browser storage APIs to persist data.
- Create custom animations using JavaScript.
- Practice string and array manipulation algorithms.
- Develop custom form validation logic and real-time feedback.
Exercise 1: Recursively Flatten a Nested Array
Learning Objective:
Understand how to recursively flatten deeply nested arrays.
function flattenArray(arr) {
return arr.reduce((acc, val) =>
Array.isArray(val) ? acc.concat(flattenArray(val)) : acc.concat(val), []
);
}
const nestedArray = [1, [2, [3, [4, [5]]]]];
console.log(flattenArray(nestedArray)); // [1, 2, 3, 4, 5]
Explanation:
- This recursive function flattens a deeply nested array into a single-level array.
- The function uses Array.reduce to iterate through the array and concatenate any nested arrays recursively.
Exercise 2: Save and Retrieve Data from Local Storage
Learning Objective:
Learn how to store and retrieve data using the browser’s local storage.
const saveButton = document.getElementById(‘save’);
const loadButton = document.getElementById(‘load’);
const inputField = document.getElementById(‘dataInput’);
saveButton.addEventListener(‘click’, () => {
const data = inputField.value;
localStorage.setItem(‘savedData’, data);
alert(‘Data saved!’);
});
loadButton.addEventListener(‘click’, () => {
const storedData = localStorage.getItem(‘savedData’);
if (storedData) {
alert(`Stored data: ${storedData}`);
} else {
alert(‘No data found’);
}
});
Explanation:
- This exercise shows how to use the localStorage API to persistently store data in the browser and retrieve it later.
- Data stored in local storage remains even after the page is refreshed or closed.
Exercise 3: Animate an Element Using requestAnimationFrame()
Learning Objective:
Learn how to create animations using the requestAnimationFrame() API.
const box = document.getElementById(‘box’);
let position = 0;
function moveBox() {
position += 2;
box.style.left = position + ‘px’;
if (position < 300) {
requestAnimationFrame(moveBox);
}
}
requestAnimationFrame(moveBox);
Explanation:
- The requestAnimationFrame() method allows smooth animations by moving the element (a box) gradually across the screen.
- It’s more efficient than setInterval() because it optimizes the rendering for smoother animation.
Exercise 4: Implement a Factorial Function Using Recursion
Learning Objective:
Learn how to use recursion to calculate the factorial of a number.
function factorial(n) {
if (n === 0) {
return 1;
}
return n * factorial(n – 1);
}
console.log(factorial(5)); // Output: 120
Explanation:
- This function uses recursion to calculate the factorial of a given number.
- The base case is n === 0, which returns 1, and the recursive case multiplies n by the factorial of n – 1.
Exercise 5: Custom Input Validation with Real-Time Feedback
Learning Objective:
Create custom form validation with real-time feedback.
<form id=”form”>
<input type=”text” id=”username” placeholder=”Enter a username”>
<p id=”feedback”></p>
<button type=”submit”>Submit</button>
</form>
<script>
const usernameInput = document.getElementById(‘username’);
const feedback = document.getElementById(‘feedback’);
usernameInput.addEventListener(‘input’, () => {
const username = usernameInput.value;
if (username.length < 5) {
feedback.textContent = ‘Username must be at least 5 characters’;
feedback.style.color = ‘red’;
} else {
feedback.textContent = ‘Username looks good!’;
feedback.style.color = ‘green’;
}
});
</script>
Explanation:
- This exercise implements real-time form validation that provides feedback as the user types into the input field.
- The feedback is based on the length of the username, which is validated live.
Exercise 6: Implementing a Binary Search Algorithm
Learning Objective:
Learn how to implement the binary search algorithm to efficiently search for a value in a sorted array.
function binarySearch(arr, target) {
let left = 0;
let right = arr.length – 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid – 1;
}
}
return -1;
}
const sortedArray = [1, 3, 5, 7, 9, 11, 13];
console.log(binarySearch(sortedArray, 7)); // Output: 3
Explanation:
- Binary search is an efficient algorithm for finding an item in a sorted array.
- This exercise demonstrates how to implement the binary search algorithm to return the index of a target value, or -1 if not found.
Exercise 7: Sorting an Array of Objects
Learning Objective:
Learn how to sort an array of objects based on a specific property.
const users = [
{ name: ‘Alice’, age: 25 },
{ name: ‘Bob’, age: 20 },
{ name: ‘Charlie’, age: 30 }
];
users.sort((a, b) => a.age – b.age);
console.log(users);
// Output: [{name: ‘Bob’, age: 20}, {name: ‘Alice’, age: 25}, {name: ‘Charlie’, age: 30}]
Explanation:
- This exercise shows how to sort an array of objects based on a particular property, in this case, the age of the users.
- The sort() function is customized to compare the age property of the objects.
Exercise 8: Debouncing Function to Prevent Excessive Function Calls
Learning Objective:
Implement a debouncing mechanism to limit the frequency of function calls during rapid events.
function debounce(func, delay) {
let timeout;
return function(…args) {
clearTimeout(timeout);
timeout = setTimeout(() => func(…args), delay);
};
}
window.addEventListener(‘resize’, debounce(() => {
console.log(‘Window resized’);
}, 500));
Explanation:
- This debouncing function ensures that the provided function is called only after a delay following the last event (in this case, window resizing).
- It prevents excessive function calls, which can improve performance in scenarios where events are triggered rapidly.
Exercise 9: Custom Sorting Algorithm (Bubble Sort)
Learning Objective:
Implement the bubble sort algorithm to sort an array of numbers.
function bubbleSort(arr) {
let swapped;
do {
swapped = false;
for (let i = 0; i < arr.length – 1; i++) {
if (arr[i] > arr[i + 1]) {
[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]; // Swap
swapped = true;
}
}
} while (swapped);
return arr;
}
const unsortedArray = [5, 2, 9, 1, 5, 6];
console.log(bubbleSort(unsortedArray)); // Output: [1, 2, 5, 5, 6, 9]
Explanation:
- This exercise implements the bubble sort algorithm, which repeatedly steps through the list and swaps adjacent elements if they are in the wrong order.
- It’s a basic sorting algorithm, useful for understanding comparison-based sorting techniques.
Exercise 10: Throttle Function to Limit Function Execution
Learning Objective:
Learn how to throttle function execution to limit how often a function can be executed during rapid events.
function throttle(func, limit) {
let inThrottle;
return function(…args) {
if (!inThrottle) {
func(…args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}
window.addEventListener(‘scroll’, throttle(() => {
console.log(‘User is scrolling’);
}, 1000));
Explanation:
- Throttling ensures that a function is executed only once within a specified period, even if the event (such as scrolling) is triggered multiple times.
- This can improve performance when dealing with frequent events.
Recap of Key Concepts:
These exercises reinforce important JavaScript concepts such as:
- Recursion: Implementing recursive solutions like flattening arrays and calculating factorials.
- Browser Storage: Using the localStorage API to persist data across page reloads.
- Animations: Creating smooth animations using requestAnimationFrame().
- Custom Input Validation: Providing real-time feedback for form input validation.
- Algorithm Implementation: Writing custom sorting algorithms (bubble sort) and search algorithms (binary search).
- Optimization Techniques: Implementing throttling and debouncing to improve performance during frequent events.
- Array and Object Manipulation: Sorting arrays of objects based on properties and shuffling arrays.
By practicing these exercises, learners will continue to strengthen their understanding of core JavaScript concepts, focusing on real-world problems and efficient algorithm implementation without relying on external libraries.