DEV Community

Cover image for JavaScript Data Structures: Managing Tasks with Arrays and Objects
Prasun Chakraborty
Prasun Chakraborty

Posted on

JavaScript Data Structures: Managing Tasks with Arrays and Objects

Introduction

Welcome back! In our previous chapter, "JavaScript Kickoff: Setting Up the Task Manager," we created a static task list. Now, let's enhance our Task Manager by exploring arrays, objects, strings, operators, control flow, and loops to make the list dynamic and interactive.

Arrays in JavaScript

Arrays are ordered lists that store multiple values in a single variable. They’re perfect for managing collections like tasks, user data, or API responses.

Key Array Methods:

  • push: Adds items to the end of an array.
  • pop: Removes the last item from an array.
  • shift: Removes the first item.
  • unshift: Adds item(s) to the start.
  • forEach: Iterates over array elements.
  • map: Creates a new array from the results of calling a function on every array element.
  • filter: Returns items matching a condition.
  • length: Indicates the number of elements in an array.
let tasks = [];
tasks.push("Learn JavaScript"); // Adds "Learn JavaScript"
tasks.push("Buy groceries"); // Adds "Buy groceries"
console.log(tasks.length); // Outputs 2
tasks.pop(); // Removes last task
tasks.forEach((task, index) => {
  console.log(`${index + 1}. ${task}`);
});// Using forEach (Prints Current item + its position (0-based))
const uppercaseTasks = tasks.map(task => task.toUpperCase()); // Using map (transforms data)
Enter fullscreen mode Exit fullscreen mode

Spread Operator (...) & Destructuring

  • Spread Operator for arrays creates a shallow copy of an array, preventing mutations to the original.
const originalTasks = ["Learn JS", "Write blog"];

// Create a copy
const tasksCopy = [...originalTasks]; 

// Add new task (won't affect original)
tasksCopy.push("Debug code"); 

// Merge task lists
const backlog = ["Fix CSS"];
const allTasks = [...backlog, ...originalTasks]; // ["Fix CSS", "Learn JS", ...]
Enter fullscreen mode Exit fullscreen mode
  • Array Destructuring unpacks array values into individual variables.
const tasks = ["Refactor code", "Test API", "Deploy"];

// Basic destructuring
const [firstTask, secondTask] = tasks; 
console.log(firstTask); // "Refactor code"

// Skip items (use commas)
const [urgentTask, , lessUrgent] = tasks; 
console.log(lessUrgent); // "Deploy"

// Default values (if undefined)
const [task1, task2, task3 = "No task"] = ["Plan sprint"];
console.log(task3); // "No task"
Enter fullscreen mode Exit fullscreen mode

JavaScript Objects

Objects store structured data as key-value pairs, perfect for organizing tasks, user profiles, or configurations.

Properties and Methods:

  • Dot Notation: task.title
  • Bracket Notation: task["priority"]
  • Destructuring: Extracts properties from objects concisely.
  • Object.keys: Returns array of keys
  • Object.values: Returns array of values
let task = { id: 1, title: "Debug API", priority: "High" };

// Accessing properties
console.log(task.title); // "Debug API"
console.log(task["priority"]); // "High"

// Destructuring
const { title, priority } = task;
console.log(title, priority);

console.log(Object.keys(task))// ["id", "title", ...]
console.log(Object.values(task)) // [1, "Debug API", ...]
Enter fullscreen mode Exit fullscreen mode

Strings and String Methods

Strings store and manipulate text data, essential for handling user input, task titles, and system messages in your applications.Useful methods include:

  • toLowerCase/toUpperCase: Converts string to lowercase or uppercase.
  • trim: Removes whitespace from the start and end.
  • includes: Check for substring in the string.
  • replace: Replace text in the string.
  • split: Convert the string to array based on a delimiter like comma or space.
  • startsWith/endsWith: Check for prefixes/suffixes in the string.
let debugString = "  !FIX the login page  ";

// Standardize format
const processedInput = debugString
  .trim()               // "!FIX the login page"
  .toLowerCase()        // "!fix the login page"
  .replace("!fix", "Urgent: Fix"); // "Urgent: Fix the login page"

console.log(processedInput); 

// Check for "!" prefix (common priority marker)
if (debugString.startsWith("!")) {.do something.}

const debugString2 = "Refactor code #backend #urgent";
const [title, ...tags] = taskWithTags.split(" #");

console.log(title);  // "Refactor code"
console.log(tags);   // ["backend", "urgent"]
Enter fullscreen mode Exit fullscreen mode

Operators and Control Flow

JavaScript uses operators for arithmetic, comparison, and logical decisions:

  • Arithmetic: + (Add/Concatenate), - (Subtract), * (Multiply), / (Divide), % (Remainder)
  • Comparison: == (equality), === (Strict equality), !== (Strict inequality), < (Less than), > (Greater than), <= (Less than or equal), >= (Greater than or equal)
  • Logical: && (AND), || (OR), ! (NOT)

Control Flow:

  • If-Else: Execute code based on conditions.
function handleTask(task) {
  if (task.priority === "Critical") {
    escalate(task);
  } else if (task.dueToday) {
    scheduleForToday(task);
  } else {
    addToBacklog(task);
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Switch: Select one of many code blocks to execute.
switch(task.priority) {
  case "Critical":
    notifyManager(task);
    break;
  case "High":
    setReminder(task);
    break;
  default:
    logTask(task); // Medium/Low priority
}
Enter fullscreen mode Exit fullscreen mode
  • Ternary Operator: Select the first if condition is true else select the other.
const status = task.completed ? "βœ… Done" : "⚠️ Pending";
// If task is completed that is task.completed is true status is done
Enter fullscreen mode Exit fullscreen mode

Loops

Automate repetitive tasks in your task manager by efficiently processing lists of tasks, reminders, or user inputs.

  • for loop: Best for known iterations (e.g., fixed task batches).
const highPriorityTasks = ["!Fix bug", "!Update docs", "!Test", "Refactor"];
for (let i = 0; i < 3 && i < highPriorityTasks.length; i++) {
  console.log(`Processing: ${highPriorityTasks[i]}`);
  markAsUrgent(highPriorityTasks[i]);
}
Enter fullscreen mode Exit fullscreen mode
  • while loop: Best for unknown iterations (e.g., processing until a condition is met).
let i = 0;
while (i < tasks.length && tasks[i].assigned) {
  console.log(`Skipping assigned task: ${tasks[i].title}`);
  i++;
}
Enter fullscreen mode Exit fullscreen mode
  • for...of Loop (Modern JS) Cleaner iteration over arrays/strings (no counter needed).
const tasks = [
  { title: "Code review", minutes: 30 },
  { title: "Meeting", minutes: 60 }
];

let totalTime = 0;
for (const task of tasks) {
  totalTime += task.minutes;
}
console.log(`Total time needed: ${totalTime} mins`);
Enter fullscreen mode Exit fullscreen mode

Project: Build a Dynamic Task Manager from Scratch II

Update the script with the below code

   const tasks = [
      { id: 1, title: "Buy groceries", priority: "High" },
      { id: 2, title: "Complete JavaScript", priority: "Critical" },
      { id: 3, title: "Read a book", priority: "Medium" }
    ];

    // Select the task-list element
    const taskList = document.getElementById('task-list');

    tasks.forEach(task => {
  let color;

  // Control flow to determine color based on priority
  switch(task.priority) {
    case "Critical":
      color = "#e74c3c"; // red
      break;
    case "High":
      color = "#f39c12"; // orange
      break;
    case "Medium":
      color = "#3498db"; // blue
      break;
    default:
      color = "#2ecc71"; // green
  }

  taskList.innerHTML += `
    <li style="color: ${color}">
      ${task.title} <span class="priority-badge">${task.priority}</span>
    </li>`;
});
Enter fullscreen mode Exit fullscreen mode

Update the CSS for the badge style

  .priority-badge {
    background: #e9ecef;
    padding: 4px 8px;
    border-radius: 12px;
    font-size: 0.8em;
    font-weight: bold;
    color: #495057;
  }
Enter fullscreen mode Exit fullscreen mode

What we have changed and achieved

  • Structured Task Data (Objects in Array): Stores tasks as objects in an array, allowing scalability to easily add/remove tasks and attaching metadata (e.g., id, priority).
  • Dynamic Rendering with forEach: Loops through tasks dynamically using forEach and generates HTML programmatically for each task.
  • Priority-Based Styling: Uses a switch statement to Check task.priority and assign a color based on priority level.
  • Dynamic Styling + Priority Badges: injects style="color: ${color}" into each <li>and adds badges as <span> to display priority text (e.g., "High").

Now You've successfully built a dynamic, color-coded task list using arrays, objects, strings, operators, control flow, and loops.

TodoOrNotTodo - Chapter 2 Branch

Stay tuned for the next chapter where we introduce event handling and interactive task management!

Enjoy building your JavaScript skills with JavaScript Deep Dive!

Top comments (4)

Collapse
 
nevodavid profile image
Nevo David

growth like this is always nice to see. kinda makes me wonder - you think keeping projects interesting gets harder as they get more complicated or easier?

Collapse
 
prasunchakra profile image
Prasun Chakraborty

cool, that's a thought-provoking question!
I think it's like bell curve, it keeps getting complicated as we proceed and is most complex in the middle of the project and then after a point of time things often start to fall into the right place and start feeling easier again.

Collapse
 
alexmustiere profile image
Alex Mustiere

Since you have IDs in your tasks, you could also use Map (or Set) as your data structure.

Collapse
 
prasunchakra profile image
Prasun Chakraborty

Thanks for the suggestions @alexmustiere! I’m definitely planning to explore Map and Set for optimizing task handling in a future post, when I will be diving deeper into data structure.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.