Skip to editor content
learningjavascript.orglesson 5 of 25

Data Structures

Data structures are ways to organize and store multiple pieces of data together. Instead of having separate variables for each piece of information, you can group related data. In this lesson, we'll learn about JavaScript's two most important data structures: arrays and objects.

What You'll Learn

  • How to create and use arrays
  • Common array methods and operations
  • How to create and use objects
  • How to access and modify object properties
  • When to use arrays vs objects

Arrays

Arrays store lists of values in order. Think of an array as a numbered list where each item has a position (index) starting from 0.

Creating Arrays

// Create an array of numbers
let numbers = [1, 2, 3, 4, 5];
console.log("Numbers:", numbers);

// Create an array of strings
let fruits = ["apple", "banana", "orange"];
console.log("Fruits:", fruits);

// Arrays can hold different types
let mixed = [1, "hello", true, 3.14];
console.log("Mixed:", mixed);

// Empty array
let empty = [];
console.log("Empty array:", empty);

Accessing Array Elements

let fruits = ["apple", "banana", "orange", "mango"];

// Access by index (starts at 0)
console.log("First fruit:", fruits[0]);
console.log("Second fruit:", fruits[1]);
console.log("Last fruit:", fruits[3]);

// Get array length
console.log("Number of fruits:", fruits.length);

// Access last element using length
console.log("Last fruit:", fruits[fruits.length - 1]);

Modifying Arrays

let numbers = [1, 2, 3];

// Change an element
numbers[1] = 20;
console.log("After change:", numbers);

// Add to the end
numbers.push(4);
console.log("After push:", numbers);

// Remove from the end
let removed = numbers.pop();
console.log("Removed:", removed);
console.log("After pop:", numbers);

// Add to the beginning
numbers.unshift(0);
console.log("After unshift:", numbers);

// Remove from the beginning
let first = numbers.shift();
console.log("First removed:", first);
console.log("After shift:", numbers);

Predict

Trace this by hand before running it. A value is pushed onto copy — but only copy, never original. What do all three lines log?

const original = [1, 2, 3];
const copy = original;
copy.push(4);

console.log("original:", original);
console.log("copy:", copy);
console.log("same array?", original === copy);

Array Methods

let numbers = [1, 2, 3, 4, 5];

// Find the index of an element
console.log("Index of 3:", numbers.indexOf(3));

// Check if array includes a value
console.log("Includes 4:", numbers.includes(4));
console.log("Includes 10:", numbers.includes(10));

// Join array into a string
let joined = numbers.join(", ");
console.log("Joined:", joined);

// Create a new array with a slice
let sliced = numbers.slice(1, 4);
console.log("Sliced (1 to 4):", sliced);
console.log("Original:", numbers);

Looping Through Arrays

let fruits = ["apple", "banana", "orange"];

// For loop
console.log("Using for loop:");
for (let i = 0; i < fruits.length; i++) {
  console.log(i + ":", fruits[i]);
}

// For...of loop (modern way)
console.log("\nUsing for...of:");
for (let fruit of fruits) {
  console.log(fruit);
}

// forEach method
console.log("\nUsing forEach:");
fruits.forEach(function(fruit, index) {
  console.log(index + ":", fruit);
});

Objects

Objects store data as key-value pairs. Instead of using numbers like arrays, objects use names (keys) to identify values.

Creating Objects

// Create an object
let person = {
  name: "Alice",
  age: 25,
  city: "New York"
};

console.log("Person:", person);

// Empty object
let empty = {};
console.log("Empty object:", empty);

Accessing Object Properties

let person = {
  name: "Alice",
  age: 25,
  city: "New York",
  isStudent: false
};

// Dot notation
console.log("Name:", person.name);
console.log("Age:", person.age);

// Bracket notation
console.log("City:", person["city"]);

// Bracket notation with variable
let property = "age";
console.log("Dynamic property:", person[property]);

Modifying Objects

let person = {
  name: "Bob",
  age: 30
};

console.log("Original:", person);

// Change a property
person.age = 31;
console.log("After age change:", person);

// Add a new property
person.city = "Boston";
console.log("After adding city:", person);

// Delete a property
delete person.age;
console.log("After deleting age:", person);

Objects with Methods

Objects can contain functions, called methods:

let calculator = {
  add: function(a, b) {
    return a + b;
  },
  subtract: function(a, b) {
    return a - b;
  },
  multiply: function(a, b) {
    return a * b;
  }
};

console.log("5 + 3 =", calculator.add(5, 3));
console.log("10 - 4 =", calculator.subtract(10, 4));
console.log("6 * 7 =", calculator.multiply(6, 7));

Looping Through Objects

let person = {
  name: "Charlie",
  age: 28,
  city: "Chicago",
  occupation: "Developer"
};

// For...in loop
console.log("Object properties:");
for (let key in person) {
  console.log(key + ":", person[key]);
}

// Get all keys
let keys = Object.keys(person);
console.log("\nAll keys:", keys);

// Get all values
let values = Object.values(person);
console.log("All values:", values);

Arrays of Objects

Combining arrays and objects is very common:

// Array of objects
let students = [
  { name: "Alice", grade: 85 },
  { name: "Bob", grade: 92 },
  { name: "Charlie", grade: 78 }
];

console.log("Students:");
for (let student of students) {
  console.log(student.name + " - Grade:", student.grade);
}

// Access specific student
console.log("\nFirst student:", students[0].name);

// Calculate average grade
let total = 0;
for (let student of students) {
  total += student.grade;
}
let average = total / students.length;
console.log("Average grade:", average);

Nested Structures

Objects can contain arrays and other objects:

let school = {
  name: "JavaScript High",
  students: ["Alice", "Bob", "Charlie"],
  location: {
    city: "Boston",
    state: "MA"
  }
};

console.log("School:", school.name);
console.log("Students:", school.students);
console.log("City:", school.location.city);

// Loop through nested array
console.log("\nStudent list:");
for (let student of school.students) {
  console.log("- " + student);
}

Debug

This code should print each student's city, using 'unknown' for anyone without an address. Instead it prints the first student's city and then crashes. Predict what it prints and why it stops, then fix it so every student prints.

const students = [
{ name: "Alice", address: { city: "Boston" } },
{ name: "Bob" },
{ name: "Charlie", address: { city: "Chicago" } },
];

console.log("Cities students live in:");
for (const student of students) {
console.log(student.name + ": " + student.address.city);
}

Expected output: Cities students live in: Alice: Boston Bob: unknown Charlie: Chicago

Recall

Without scrolling up: you have an array of student objects, each with a grade, and you want to count how many scored 80 or higher. Which two tools from earlier lessons do you combine to do it?

Try It Yourself

Reading about arrays and objects is not the same as building with them. This is a build task: a small program that reports its own pass/fail. You are given a roster of students — an array of objects — and three empty functions to finish. Run it and it fails immediately, telling you which function is still missing. Implement each one until every check passes and it prints All checks passed.

The three functions reuse exactly what this lesson taught: looping over an array of objects, reading a field with dot notation, aggregating with a running total, and building up an object as you go. The starter already has the data, the stubs, and the checks — you write only the logic inside each function. Nothing above spells out all three answers, so you will have to assemble them yourself.

Build

Finish the build. Three functions are stubbed out and the checks below them fail until each one returns the right value. Run it as-is to see which check fails first, decide what that function is missing, then implement the three functions until it prints 'All checks passed.' The checks run top to bottom, so the first failure you see is TODO 1 — implement it first, then work down.

const assert = require('assert');

// The data: a class roster. Do NOT change this array.
const students = [
{ name: "Alice", city: "Boston", grade: 91 },
{ name: "Bob", city: "Boston", grade: 78 },
{ name: "Carol", city: "Denver", grade: 84 },
{ name: "Dan", city: "Denver", grade: 88 },
{ name: "Eve", city: "Boston", grade: 72 },
];

// TODO 1: return a NEW array of just the names, in order.
//   names(students) -> ["Alice", "Bob", "Carol", "Dan", "Eve"]
function names(students) {
// your code here
}

// TODO 2: return the class average grade as a number.
//   averageGrade(students) -> 82.6
function averageGrade(students) {
// your code here
}

// TODO 3: return an object counting how many students are in each city.
//   countByCity(students) -> { Boston: 3, Denver: 2 }
function countByCity(students) {
// your code here
}

// --- Build checks: these must all pass. Do not edit below this line. ---
assert.deepStrictEqual(
names(students),
["Alice", "Bob", "Carol", "Dan", "Eve"],
"names(students) should return an array of every student's name, in order",
);
assert.strictEqual(
averageGrade(students),
82.6,
"averageGrade(students) should return the mean of all grades (82.6)",
);
assert.deepStrictEqual(
countByCity(students),
{ Boston: 3, Denver: 2 },
"countByCity(students) should map each city to how many students live there",
);

console.log("All checks passed.");
console.log("Names:", names(students));
console.log("Average grade:", averageGrade(students));
console.log("By city:", countByCity(students));

Expected output: All checks passed. Names: [ 'Alice', 'Bob', 'Carol', 'Dan', 'Eve' ] Average grade: 82.6 By city: { Boston: 3, Denver: 2 }

Once it passes, try two variations and predict each before running:

  1. Push the whole student. In names, push student instead of student.name. Predict the shape of what names(students) returns before running. You get an array of the full objects, not their names, so the deepStrictEqual against ["Alice", ...] fails — a reminder that building a projection means pulling out the one field, not the whole record.
  2. Drop the first-seen guard. In countByCity, count with a bare counts[student.city] = counts[student.city] + 1, with no branch that starts an unseen city at 0. Predict what countByCity(students) returns before running. The first time a city is seen, counts[city] is undefined, and undefined + 1 is NaN — so every city comes out NaN, showing why the count-up object needs an initial value.

Capstone milestone

Milestone — the data behind the Task Manager service. The capstone keeps its tasks as an array of task objects, each with fields like title and status, and the service reads and updates that array. This lesson's arrays-of-objects are that exact data shape in miniature. Confirm you can model and read it.

Hint: You don't need the capstone service itself yet — this confirms the array-of-objects data model it sits on. In the capstone, the service holds tasks as exactly this kind of array and reads their fields the same way.

  • Built an array of objects where each object holds several named fields
  • Accessed a field on one object with dot or bracket notation
  • Looped over the array to read a field from every object
  • Aggregated across the array (a count, a total, or an average) with a loop

Key Takeaways

  • Arrays store ordered lists of values, accessed by index (0, 1, 2, ...)
  • Use arrays when you need an ordered collection of similar items
  • Objects store key-value pairs, accessed by property name
  • Use objects when you need to group related properties together
  • Arrays and objects can be nested to create complex data structures
  • Common array methods: push(), pop(), shift(), unshift(), indexOf(), includes()
  • Access object properties with dot notation (obj.key) or bracket notation (obj["key"])

Next Steps

You can now organize data with arrays and objects — which sets up the next core lesson perfectly. Next you'll learn array methods like map, filter, and reduce: the tools that turn the arrays you just met into concise, expressive data pipelines you'll reach for constantly.

Pro Tip: The best way to master data structures is to use them in real projects. Try creating a todo list with an array of objects, or a contact book using nested objects. Practice makes perfect!

Next lesson

Array Methods

JavaScript array methods tutorial — master map, filter, reduce, find, some, every, and more with interactive examples you can edit and run

25 min