Practice Questions — Project: Build a To-Do App with Local Storage
← Back to NotesTopic-Specific Questions
Question 1
Easy
What is the output?
const tasks = [];
tasks.push({ id: 1, text: "Learn JS", completed: false });
tasks.push({ id: 2, text: "Build app", completed: false });
console.log(tasks.length);
console.log(tasks[0].text);push adds items to the array. Access properties with dot notation.
2Learn JSQuestion 2
Easy
What is the output?
const tasks = [
{ id: 1, text: "A", completed: false },
{ id: 2, text: "B", completed: true },
{ id: 3, text: "C", completed: false }
];
const active = tasks.filter(function(t) { return !t.completed; });
console.log(active.length);
console.log(active[0].text);filter keeps items where the callback returns true. !false is true.
2AQuestion 3
Easy
What is the output?
const task = { id: 1, text: "Learn JS", completed: false };
task.completed = !task.completed;
console.log(task.completed);
task.completed = !task.completed;
console.log(task.completed);!false is true, !true is false.
truefalseQuestion 4
Easy
What is the output?
const tasks = [
{ id: 1, text: "A" },
{ id: 2, text: "B" },
{ id: 3, text: "C" }
];
const filtered = tasks.filter(function(t) { return t.id !== 2; });
console.log(filtered.length);
filtered.forEach(function(t) { console.log(t.text); });filter keeps items where the condition is true. id !== 2 is true for tasks 1 and 3.
2ACQuestion 5
Medium
What is the output?
const tasks = [
{ id: 1, text: "X", completed: false },
{ id: 2, text: "Y", completed: true },
{ id: 3, text: "Z", completed: false }
];
const remaining = tasks.filter(function(t) { return !t.completed; }).length;
console.log(remaining + " item" + (remaining !== 1 ? "s" : "") + " left");2 items are not completed. The ternary adds 's' for plural.
2 items leftQuestion 6
Medium
What is the output?
let tasks = [
{ id: 1, text: "A", completed: false },
{ id: 2, text: "B", completed: true }
];
tasks = tasks.map(function(task) {
if (task.id === 1) {
return { id: task.id, text: task.text, completed: !task.completed };
}
return task;
});
console.log(tasks[0].completed);
console.log(tasks[1].completed);map creates a new array. Only task with id 1 is modified.
truetrueQuestion 7
Medium
What is the output?
const id1 = Date.now();
const id2 = Date.now();
console.log(id1 === id2);
console.log(typeof id1);Date.now() runs so fast that both calls happen in the same millisecond.
truenumberQuestion 8
Hard
What is the output?
let tasks = [
{ id: 1, text: "A", completed: true },
{ id: 2, text: "B", completed: false },
{ id: 3, text: "C", completed: true },
{ id: 4, text: "D", completed: false }
];
// Clear completed
tasks = tasks.filter(function(t) { return !t.completed; });
console.log(tasks.length);
tasks.forEach(function(t) { console.log(t.text); });filter keeps tasks where completed is false.
2BDQuestion 9
Easy
Why do we use Date.now() as the task ID instead of the array index?
Think about what happens when you delete a task or filter the list.
Array indices change when items are added, removed, or filtered. If you delete the task at index 0, all other indices shift down. But a Date.now() ID stays the same regardless of what happens to the array. It uniquely identifies the task forever.
Question 10
Medium
Why does the renderTasks function call
list.innerHTML = "" before adding task elements?What would happen if you did not clear the list?
Without clearing, each call to renderTasks would append new elements to the existing ones. After toggling a task, you would see the original list plus a duplicate list. Clearing first ensures the list always matches the current state of the data.
Question 11
Hard
What is CRUD and how does the to-do app implement each operation?
CRUD stands for Create, Read, Update, Delete.
Create: the addTask function pushes a new task object to the array. Read: the renderTasks function reads the array and displays tasks on screen. Update: toggleTask and editTask modify task properties (completed, text). Delete: deleteTask removes a task using filter. These four operations are the backbone of nearly every web application.
Question 12
Easy
What is the output?
const tasks = [
{ id: 1, text: "A", completed: false },
{ id: 2, text: "B", completed: true }
];
console.log(JSON.stringify(tasks));JSON.stringify converts the array to a string.
[{"id":1,"text":"A","completed":false},{"id":2,"text":"B","completed":true}]Question 13
Easy
What is the output?
const ul = document.createElement('ul');
const li = document.createElement('li');
li.textContent = 'Task 1';
ul.appendChild(li);
console.log(ul.children.length);
console.log(ul.children[0].textContent);appendChild adds the li to the ul. children gives child elements.
1Task 1Question 14
Medium
What is the output?
const tasks = [
{ id: 1, text: "A", completed: true },
{ id: 2, text: "B", completed: false },
{ id: 3, text: "C", completed: true }
];
const result = tasks.map(function(t) {
if (t.id === 2) return { id: t.id, text: t.text, completed: true };
return t;
});
console.log(result[1].completed);
console.log(tasks[1].completed);map creates a new array. The original is unchanged.
truefalseQuestion 15
Medium
What is the output?
const el = document.createElement('span');
el.classList.add('task-text');
el.classList.add('completed');
console.log(el.className);
el.classList.remove('completed');
console.log(el.className);classList.add adds classes, classList.remove removes them.
task-text completedtask-textQuestion 16
Hard
What is the output?
let tasks = [
{ id: 1, text: "A", completed: false },
{ id: 2, text: "B", completed: true },
{ id: 3, text: "C", completed: false }
];
// Toggle task 1
tasks = tasks.map(function(t) {
return t.id === 1 ? { id: t.id, text: t.text, completed: !t.completed } : t;
});
// Delete task 2
tasks = tasks.filter(function(t) { return t.id !== 2; });
// Clear completed
tasks = tasks.filter(function(t) { return !t.completed; });
console.log(tasks.length);
console.log(tasks[0].text);Track each operation: toggle makes task 1 completed, delete removes task 2, clear completed removes task 1.
1CQuestion 17
Medium
Why does the to-do app use innerHTML = '' before rendering tasks instead of removing individual elements?
Think about simplicity vs performance.
Setting
innerHTML = '' is the simplest approach -- it clears everything in one step, then the render function rebuilds the list from the data array. Removing individual elements would require tracking which ones changed, which is more complex. For a small to-do list (tens of items), the performance difference is negligible, and simplicity is more important.Mixed & Application Questions
Question 1
Easy
What is the output?
const text = " Learn JavaScript ";
console.log(text.trim());
console.log(text.trim() === "");trim() removes whitespace from both ends of a string.
Learn JavaScriptfalseQuestion 2
Easy
What is the output?
const el = document.createElement("li");
el.classList.add("task-item");
el.classList.add("completed");
console.log(el.classList.contains("task-item"));
console.log(el.classList.contains("active"));
console.log(el.className);classList.add adds classes, contains checks if a class exists.
truefalsetask-item completedQuestion 3
Medium
What is the output?
const tasks = [
{ id: 1, text: "A", completed: false },
{ id: 2, text: "B", completed: true },
{ id: 3, text: "C", completed: false }
];
const found = tasks.find(function(t) { return t.id === 2; });
console.log(found.text);
const notFound = tasks.find(function(t) { return t.id === 99; });
console.log(notFound);find returns the first matching element, or undefined if none found.
BundefinedQuestion 4
Medium
What is the output?
const btn = document.createElement("button");
btn.dataset.filter = "active";
console.log(btn.dataset.filter);
console.log(btn.getAttribute("data-filter"));dataset accesses data-* attributes. data-filter becomes dataset.filter.
activeactiveQuestion 5
Medium
What is the output?
let tasks = [
{ id: 1, text: "A", completed: false },
{ id: 2, text: "B", completed: false }
];
localStorage.setItem("tasks", JSON.stringify(tasks));
tasks[0].completed = true;
const saved = JSON.parse(localStorage.getItem("tasks"));
console.log(saved[0].completed);Does changing the array in memory automatically update localStorage?
falseQuestion 6
Hard
What is the output?
const tasks = [
{ id: 1, text: "JS", completed: false },
{ id: 2, text: "CSS", completed: true },
{ id: 3, text: "HTML", completed: false },
{ id: 4, text: "React", completed: true }
];
const activeTexts = tasks
.filter(function(t) { return !t.completed; })
.map(function(t) { return t.text; });
console.log(activeTexts);filter keeps active tasks, then map extracts just the text.
["JS", "HTML"]Question 7
Hard
What is the output?
function addTask(tasks, text) {
return tasks.concat([{ id: Date.now(), text: text, completed: false }]);
}
let tasks = [];
tasks = addTask(tasks, "A");
tasks = addTask(tasks, "B");
console.log(tasks.length);
const original = [];
const updated = addTask(original, "C");
console.log(original.length);
console.log(updated.length);concat returns a NEW array. It does not modify the original.
201Question 8
Hard
What is the output?
const span = document.createElement("span");
span.textContent = "Learn JavaScript";
span.contentEditable = true;
console.log(span.contentEditable);
console.log(span.isContentEditable);
span.contentEditable = false;
console.log(span.contentEditable);
console.log(span.isContentEditable);contentEditable is a string attribute. isContentEditable is a boolean.
truetruefalsefalseQuestion 9
Easy
What is the output?
const input = document.createElement('input');
input.value = ' Learn JavaScript ';
console.log(input.value.trim());
console.log(input.value.trim().length);trim() removes whitespace from both ends.
Learn JavaScript16Question 10
Medium
What is the output?
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = false;
console.log(checkbox.checked);
checkbox.checked = !checkbox.checked;
console.log(checkbox.checked);The ! operator flips a boolean.
falsetrueQuestion 11
Medium
What is the output?
const tasks = [
{ id: 1, text: "JS" },
{ id: 2, text: "CSS" },
{ id: 3, text: "HTML" }
];
const idx = tasks.findIndex(function(t) { return t.id === 2; });
console.log(idx);
console.log(tasks[idx].text);findIndex returns the index of the first matching element.
1CSSQuestion 12
Hard
What is the output?
const el = document.createElement('span');
el.addEventListener('blur', function() {
console.log('blur fired');
}, { once: true });
// Simulate two blurs
el.dispatchEvent(new Event('blur'));
el.dispatchEvent(new Event('blur'));{ once: true } removes the listener after it fires once.
blur fired (printed only once)Question 13
Hard
What is the output?
let tasks = [
{ id: 1, text: "A", completed: false },
{ id: 2, text: "B", completed: false }
];
localStorage.setItem('tasks', JSON.stringify(tasks));
tasks.push({ id: 3, text: "C", completed: false });
localStorage.setItem('tasks', JSON.stringify(tasks));
const loaded = JSON.parse(localStorage.getItem('tasks'));
console.log(loaded.length);
console.log(loaded[2].text);The second setItem overwrites the first save.
3CMultiple Choice Questions
MCQ 1
What does CRUD stand for in web development?
Answer: B
B is correct. CRUD stands for Create, Read, Update, Delete. These are the four basic operations for managing data in any application.
B is correct. CRUD stands for Create, Read, Update, Delete. These are the four basic operations for managing data in any application.
MCQ 2
Which array method is best for deleting a task by its ID?
Answer: C
C is correct.
C is correct.
filter creates a new array excluding the task with the matching ID: tasks.filter(t => t.id !== id). splice works but requires finding the index first. pop and shift only remove from the end/start.MCQ 3
Why do we use Date.now() for task IDs?
Answer: B
B is correct. Date.now() returns the current time in milliseconds, which is practically unique for each task creation. It is simple and does not require a counter variable.
B is correct. Date.now() returns the current time in milliseconds, which is practically unique for each task creation. It is simple and does not require a counter variable.
MCQ 4
What CSS property creates a line through completed task text?
Answer: B
B is correct.
B is correct.
text-decoration: line-through draws a line through the text. This is applied when the task has the .completed CSS class.MCQ 5
Which array method is used to toggle a task's completed status immutably?
Answer: C
C is correct.
C is correct.
map creates a new array where the matching task has completed: !task.completed and all other tasks are unchanged. This is the immutable approach.MCQ 6
What does contentEditable do to an HTML element?
Answer: C
C is correct. Setting
C is correct. Setting
contentEditable = true allows the user to click on the element and type to change its text, like a text input but on any element.MCQ 7
Why do we clear innerHTML before re-rendering the task list?
Answer: B
B is correct. Without clearing, each render call would append new elements after the existing ones, causing duplicates. Clearing first ensures the list matches the current data.
B is correct. Without clearing, each render call would append new elements after the existing ones, causing duplicates. Clearing first ensures the list matches the current data.
MCQ 8
What does the { once: true } option do for addEventListener?
Answer: B
B is correct.
B is correct.
{ once: true } automatically removes the event listener after it fires once. This is useful for the blur event on editable tasks -- we only want to save once when editing ends.MCQ 9
What is the data flow pattern used in the to-do app?
Answer: B
B is correct. Every user action triggers: update the tasks array, save to localStorage, re-render the UI from the array. This unidirectional data flow is the same pattern used by React and other modern frameworks.
B is correct. Every user action triggers: update the tasks array, save to localStorage, re-render the UI from the array. This unidirectional data flow is the same pattern used by React and other modern frameworks.
MCQ 10
Why is using array.filter() for deletion better than array.splice()?
Answer: B
B is correct.
B is correct.
filter returns a new array, which is the immutable approach. splice modifies the original array in place. While both work, filter is cleaner and aligns with modern functional programming practices.MCQ 11
What happens if two tasks are added in the same millisecond using Date.now() as the ID?
Answer: B
B is correct. If Date.now() is called twice in the same millisecond, both return the same value. This is extremely rare in manual user interaction (humans cannot click that fast). For production apps, use crypto.randomUUID() or a library for truly unique IDs.
B is correct. If Date.now() is called twice in the same millisecond, both return the same value. This is extremely rare in manual user interaction (humans cannot click that fast). For production apps, use crypto.randomUUID() or a library for truly unique IDs.
MCQ 12
What is the purpose of the data-filter attribute on the filter buttons?
Answer: B
B is correct. The
B is correct. The
data-filter attribute stores the filter type ("all", "active", "completed"). When clicked, JavaScript reads btn.dataset.filter to know which filter to apply.MCQ 13
What does input.value.trim() do?
Answer: B
B is correct.
B is correct.
trim() removes whitespace from both ends of a string. It does not remove spaces in the middle.MCQ 14
What is the benefit of using event delegation for the delete buttons?
Answer: B
B is correct. Event delegation uses one listener on a parent element instead of individual listeners on each child. This handles dynamically created elements automatically.
B is correct. Event delegation uses one listener on a parent element instead of individual listeners on each child. This handles dynamically created elements automatically.
MCQ 15
What does the Escape key do during task editing in the to-do app?
Answer: C
C is correct. Pressing Escape restores the original task text and exits edit mode. Enter saves the changes, and Escape cancels them.
C is correct. Pressing Escape restores the original task text and exits edit mode. Enter saves the changes, and Escape cancels them.
Coding Challenges
Challenge 1: Add Due Dates to Tasks
EasyModify the to-do app to include a due date for each task. Add a date input next to the task input. Display the due date next to each task. Highlight tasks that are overdue (due date is in the past) with a red border.
Sample Input
Task: 'Finish homework', Due: '2026-04-10'
Sample Output
[ ] Finish homework (Due: Apr 10) [Delete]
[!] Overdue tasks shown with red border
Store the due date in the task object. Use new Date() to compare dates.
// Modified task structure
// { id: Date.now(), text: "Finish homework", completed: false, dueDate: "2026-04-10" }
function addTask() {
const text = document.getElementById("taskInput").value.trim();
const dueDate = document.getElementById("dateInput").value;
if (text === "") return;
tasks.push({ id: Date.now(), text: text, completed: false, dueDate: dueDate || null });
saveTasks();
renderTasks();
}
// In renderTasks, check if overdue
function isOverdue(task) {
if (!task.dueDate || task.completed) return false;
return new Date(task.dueDate) < new Date();
}
// Add red border class if overdue
if (isOverdue(task)) {
li.style.borderColor = "#ef4444";
}Challenge 2: Add Task Categories/Tags
MediumAdd a category system to tasks. Users can tag tasks as 'Work', 'Personal', 'Study', or 'Other'. Add a dropdown for category selection when adding tasks. Add filter buttons for each category. Show a colored dot next to each task based on its category.
Sample Input
Task: 'Read chapter 23', Category: 'Study'
Sample Output
Categories: [All] [Work] [Personal] [Study]
[purple dot] Read chapter 23 [Delete]
[blue dot] Fix bug in code [Delete]
Store category in the task object. Add color mapping for each category.
const categoryColors = {
work: "#3b82f6",
personal: "#10b981",
study: "#a855f7",
other: "#94a3b8"
};
function addTask() {
const text = document.getElementById("taskInput").value.trim();
const category = document.getElementById("categorySelect").value;
if (text === "") return;
tasks.push({ id: Date.now(), text: text, completed: false, category: category });
saveTasks();
renderTasks();
}
// In renderTasks, add category dot
const dot = document.createElement("span");
dot.style.width = "10px";
dot.style.height = "10px";
dot.style.borderRadius = "50%";
dot.style.background = categoryColors[task.category] || "#94a3b8";
li.prepend(dot);
// Add category filter
function filterByCategory(cat) {
if (cat === "all") return tasks;
return tasks.filter(function(t) { return t.category === cat; });
}Challenge 3: Drag and Drop Reordering
HardAdd drag-and-drop functionality to reorder tasks. Users should be able to drag a task and drop it at a new position in the list. The new order should be saved to localStorage.
Sample Input
Drag task 3 above task 1
Sample Output
Tasks reordered:
1. (was task 3)
2. (was task 1)
3. (was task 2)
Order saved to localStorage.
Use the HTML Drag and Drop API (draggable, dragstart, dragover, drop events).
// Make task items draggable
li.draggable = true;
li.dataset.id = task.id;
li.addEventListener("dragstart", function(e) {
e.dataTransfer.setData("text/plain", task.id);
li.classList.add("dragging");
});
li.addEventListener("dragend", function() {
li.classList.remove("dragging");
});
// Allow dropping on the task list
const list = document.getElementById("taskList");
list.addEventListener("dragover", function(e) {
e.preventDefault();
const dragging = document.querySelector(".dragging");
const siblings = Array.from(list.querySelectorAll(".task-item:not(.dragging)"));
const nextSibling = siblings.find(function(sib) {
const box = sib.getBoundingClientRect();
return e.clientY < box.top + box.height / 2;
});
list.insertBefore(dragging, nextSibling || null);
});
list.addEventListener("drop", function(e) {
e.preventDefault();
// Read new order from DOM
const newOrder = Array.from(list.children).map(function(li) {
return Number(li.dataset.id);
});
// Reorder tasks array to match
tasks = newOrder.map(function(id) {
return tasks.find(function(t) { return t.id === id; });
});
saveTasks();
});Challenge 4: Task Statistics Dashboard
MediumAdd a statistics section that shows: total tasks, completed tasks, completion percentage, most productive day (day with most tasks completed), and a simple bar showing completion progress.
Sample Input
(5 tasks total, 3 completed)
Sample Output
Stats:
Total: 5 | Completed: 3 | Active: 2
Completion: 60%
[====------] 60%
Calculate stats from the tasks array. Display a visual progress bar using a div with dynamic width.
function showStats() {
const total = tasks.length;
const completed = tasks.filter(function(t) { return t.completed; }).length;
const active = total - completed;
const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;
const statsEl = document.getElementById("stats");
statsEl.innerHTML = '<p>Total: ' + total + ' | Completed: ' + completed + ' | Active: ' + active + '</p>' +
'<p>Completion: ' + percentage + '%</p>' +
'<div class="progress-bar">' +
'<div class="progress-fill" style="width: ' + percentage + '%"></div>' +
'</div>';
}
// Call showStats() inside renderTasks()
// CSS for progress bar:
// .progress-bar { height: 8px; background: #334155; border-radius: 4px; }
// .progress-fill { height: 100%; background: #a855f7; border-radius: 4px; transition: width 0.3s; }Challenge 5: Export and Import Tasks
HardAdd buttons to export all tasks as a JSON file (download) and import tasks from a JSON file (upload). This lets users back up their tasks or transfer them between devices.
Sample Input
Click 'Export' to download tasks.json, or click 'Import' to upload a file.
Sample Output
Exported 5 tasks to tasks.json
Imported 5 tasks from file
Use Blob and URL.createObjectURL for export. Use FileReader for import.
// Export tasks as JSON file
function exportTasks() {
const data = JSON.stringify(tasks, null, 2);
const blob = new Blob([data], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "tasks.json";
a.click();
URL.revokeObjectURL(url);
console.log("Exported " + tasks.length + " tasks");
}
// Import tasks from JSON file
function importTasks(file) {
const reader = new FileReader();
reader.onload = function(e) {
try {
const imported = JSON.parse(e.target.result);
if (Array.isArray(imported)) {
tasks = imported;
saveTasks();
renderTasks();
console.log("Imported " + imported.length + " tasks");
}
} catch (err) {
console.log("Invalid file format");
}
};
reader.readAsText(file);
}
// File input for import
document.getElementById("importInput").addEventListener("change", function(e) {
if (e.target.files[0]) importTasks(e.target.files[0]);
});Challenge 6: Undo Delete Feature
HardAdd an undo feature. When a task is deleted, show a toast notification with an 'Undo' button. If the user clicks Undo within 5 seconds, the task is restored. After 5 seconds, the toast disappears and the deletion is final.
Sample Input
Delete task 'Learn JavaScript', click Undo within 5 seconds
Sample Output
Task deleted. [Undo - 5s]
(Click Undo)
Task restored: Learn JavaScript
Store the deleted task temporarily. Use setTimeout for auto-dismiss.
let lastDeleted = null;
let undoTimeout = null;
function deleteTask(id) {
const task = tasks.find(function(t) { return t.id === id; });
lastDeleted = { task: task, index: tasks.indexOf(task) };
tasks = tasks.filter(function(t) { return t.id !== id; });
saveTasks();
renderTasks();
showUndoToast();
}
function showUndoToast() {
const toast = document.getElementById("undoToast");
toast.textContent = 'Task deleted. ';
const undoBtn = document.createElement("button");
undoBtn.textContent = "Undo";
undoBtn.addEventListener("click", function() {
if (lastDeleted) {
tasks.splice(lastDeleted.index, 0, lastDeleted.task);
saveTasks();
renderTasks();
lastDeleted = null;
}
toast.style.display = "none";
clearTimeout(undoTimeout);
});
toast.appendChild(undoBtn);
toast.style.display = "block";
clearTimeout(undoTimeout);
undoTimeout = setTimeout(function() {
toast.style.display = "none";
lastDeleted = null;
}, 5000);
}Need to Review the Concepts?
Go back to the detailed notes for this chapter.
Read Chapter NotesWant to learn web development with a live mentor?
Explore our Frontend Masterclass