Lesson 04.3: Arrays & Objects
Duration: 60 minutes | Difficulty: Beginner
Learning Objectives
By the end of this lesson, you will:
- Create and manipulate arrays
- Create and work with objects
- Use destructuring for cleaner code
- Combine arrays and objects effectively
Arrays: Ordered Lists
Arrays store ordered collections of items.
Creating Arrays
// Array literal (preferred)
const fruits = ["apple", "banana", "orange"];
// Array constructor (rarely used)
const numbers = new Array(1, 2, 3);
// Empty array
const empty = [];
// Mixed types (possible, but usually avoid)
const mixed = [1, "two", true, null];
Accessing Elements
const colors = ["red", "green", "blue"];
// By index (0-based)
console.log(colors[0]); // "red"
console.log(colors[1]); // "green"
console.log(colors[2]); // "blue"
console.log(colors[3]); // undefined (out of bounds)
// Last element
console.log(colors[colors.length - 1]); // "blue"
// Modern: at() method
console.log(colors.at(-1)); // "blue" (negative index from end)
Modifying Arrays
const tasks = ["code", "test", "deploy"];
// Add to end
tasks.push("document"); // ["code", "test", "deploy", "document"]
// Add to beginning
tasks.unshift("plan"); // ["plan", "code", "test", "deploy", "document"]
// Remove from end
const last = tasks.pop(); // "document" (removed)
// Remove from beginning
const first = tasks.shift(); // "plan" (removed)
// Modify by index
tasks[1] = "review"; // ["code", "review", "deploy"]
// Remove/insert at position
tasks.splice(1, 1); // Remove 1 item at index 1
tasks.splice(1, 0, "test"); // Insert "test" at index 1
tasks.splice(1, 1, "qa", "uat"); // Replace 1 item with 2 items
Array Methods (Non-mutating)
const numbers = [1, 2, 3, 4, 5];
// slice: Extract portion (doesn't modify original)
const middle = numbers.slice(1, 4); // [2, 3, 4]
// concat: Combine arrays
const more = numbers.concat([6, 7, 8]); // [1, 2, 3, 4, 5, 6, 7, 8]
// join: Convert to string
const str = numbers.join(", "); // "1, 2, 3, 4, 5"
// includes: Check if contains
const hasThree = numbers.includes(3); // true
// indexOf: Find position
const position = numbers.indexOf(3); // 2
Iterating Arrays
const items = ["a", "b", "c"];
// for loop
for (let i = 0; i < items.length; i++) {
console.log(items[i]);
}
// for...of (preferred for values)
for (const item of items) {
console.log(item);
}
// forEach
items.forEach((item, index) => {
console.log(`${index}: ${item}`);
});
// map (transform each item)
const upper = items.map(item => item.toUpperCase());
// ["A", "B", "C"]
Objects: Key-Value Pairs
Objects store data as key-value pairs.
Creating Objects
// Object literal (preferred)
const user = {
name: "Alice",
age: 30,
email: "alice@example.com"
};
// Object constructor (rarely used)
const obj = new Object();
obj.key = "value";
Accessing Properties
const user = {
name: "Alice",
age: 30,
"full-name": "Alice Smith" // Quoted key for special characters
};
// Dot notation (preferred)
console.log(user.name); // "Alice"
// Bracket notation (for dynamic keys or special characters)
console.log(user["name"]); // "Alice"
console.log(user["full-name"]); // "Alice Smith"
// Dynamic key
const key = "age";
console.log(user[key]); // 30
Modifying Objects
const person = {
name: "Alice"
};
// Add property
person.age = 30;
person["email"] = "alice@example.com";
// Update property
person.name = "Alice Smith";
// Delete property
delete person.email;
// Check if property exists
console.log("name" in person); // true
console.log(person.hasOwnProperty("age")); // true
Object Methods
const user = {
name: "Alice",
age: 30,
greet: function() {
return `Hello, I'm ${this.name}`;
},
// Shorthand method syntax
introduce() {
return `I'm ${this.age} years old`;
}
};
console.log(user.greet()); // "Hello, I'm Alice"
console.log(user.introduce()); // "I'm 30 years old"
Object Utilities
const config = {
host: "localhost",
port: 3000,
debug: true
};
// Get all keys
Object.keys(config); // ["host", "port", "debug"]
// Get all values
Object.values(config); // ["localhost", 3000, true]
// Get key-value pairs
Object.entries(config); // [["host", "localhost"], ["port", 3000], ["debug", true]]
// Iterate over entries
for (const [key, value] of Object.entries(config)) {
console.log(`${key}: ${value}`);
}
Destructuring
Extract values from arrays/objects into variables.
Array Destructuring
const rgb = [255, 128, 64];
// Without destructuring
const red = rgb[0];
const green = rgb[1];
const blue = rgb[2];
// With destructuring
const [r, g, b] = rgb;
console.log(r, g, b); // 255 128 64
// Skip elements
const [first, , third] = rgb;
console.log(first, third); // 255 64
// Rest pattern
const [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]
// Default values
const [a, b, c = 0] = [1, 2];
console.log(c); // 0
Object Destructuring
const user = {
name: "Alice",
email: "alice@example.com",
age: 30
};
// Without destructuring
const name = user.name;
const email = user.email;
// With destructuring
const { name, email } = user;
console.log(name, email); // "Alice" "alice@example.com"
// Rename variables
const { name: userName, email: userEmail } = user;
console.log(userName, userEmail);
// Default values
const { name, role = "user" } = user;
console.log(role); // "user"
// Nested destructuring
const response = {
data: {
user: {
id: 1,
name: "Alice"
}
}
};
const { data: { user: { id, name } } } = response;
console.log(id, name); // 1 "Alice"
Spread Operator
Expand arrays/objects.
Array Spread
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// Combine arrays
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// Copy array
const copy = [...arr1];
// Add elements while spreading
const extended = [0, ...arr1, 4]; // [0, 1, 2, 3, 4]
// Function arguments
const numbers = [1, 2, 3];
console.log(Math.max(...numbers)); // 3
Object Spread
const defaults = {
theme: "light",
language: "en"
};
const userPrefs = {
theme: "dark"
};
// Merge objects (later properties override)
const settings = { ...defaults, ...userPrefs };
// { theme: "dark", language: "en" }
// Copy with additions
const extended = { ...settings, fontSize: 14 };
Common Patterns
Filtering Objects
const users = [
{ name: "Alice", role: "admin", active: true },
{ name: "Bob", role: "user", active: false },
{ name: "Charlie", role: "user", active: true }
];
// Find active users
const activeUsers = users.filter(user => user.active);
// Find admins
const admins = users.filter(user => user.role === "admin");
// Find by name
const alice = users.find(user => user.name === "Alice");
Transforming Data
const products = [
{ name: "Laptop", price: 999 },
{ name: "Phone", price: 699 },
{ name: "Tablet", price: 499 }
];
// Get just names
const names = products.map(p => p.name);
// ["Laptop", "Phone", "Tablet"]
// Calculate total
const total = products.reduce((sum, p) => sum + p.price, 0);
// 2197
// Transform structure
const priceList = products.map(p => ({
item: p.name,
cost: `$${p.price}`
}));
// [{ item: "Laptop", cost: "$999" }, ...]
Grouping Data
const tasks = [
{ id: 1, status: "done" },
{ id: 2, status: "pending" },
{ id: 3, status: "done" },
{ id: 4, status: "pending" }
];
// Group by status
const grouped = tasks.reduce((acc, task) => {
const key = task.status;
if (!acc[key]) acc[key] = [];
acc[key].push(task);
return acc;
}, {});
// {
// done: [{ id: 1, ... }, { id: 3, ... }],
// pending: [{ id: 2, ... }, { id: 4, ... }]
// }
SpecWeave Connection
SpecWeave's data structures map directly to JavaScript:
spec.md User Stories as Objects
// User story from spec.md
const userStory = {
id: "US-001",
title: "User Login",
asA: "registered user",
iWant: "log in with my credentials",
soThat: "I can access my account",
acceptanceCriteria: [
{ id: "AC-US1-01", description: "User can enter email and password", complete: false },
{ id: "AC-US1-02", description: "Invalid credentials show error", complete: false },
{ id: "AC-US1-03", description: "Successful login redirects", complete: false }
]
};
// Check progress
const completedACs = userStory.acceptanceCriteria.filter(ac => ac.complete);
const progress = (completedACs.length / userStory.acceptanceCriteria.length) * 100;
tasks.md Tasks as Array
// Tasks from tasks.md
const tasks = [
{ id: "T-001", userStory: "US-001", status: "completed", satisfies: ["AC-US1-01"] },
{ id: "T-002", userStory: "US-001", status: "in_progress", satisfies: ["AC-US1-02"] },
{ id: "T-003", userStory: "US-001", status: "pending", satisfies: ["AC-US1-03"] }
];
// Filter by status
const pendingTasks = tasks.filter(t => t.status === "pending");
const completedTasks = tasks.filter(t => t.status === "completed");
// Find tasks for a user story
const storyTasks = tasks.filter(t => t.userStory === "US-001");
// Get all ACs covered
const coveredACs = tasks.flatMap(t => t.satisfies);
// ["AC-US1-01", "AC-US1-02", "AC-US1-03"]
Practice Exercise
// Exercise 1: Array Operations
// Given this array, find all even numbers and double them
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Expected: [4, 8, 12, 16, 20]
// Exercise 2: Object Manipulation
// Merge these objects, with user preferences taking priority
const defaults = { theme: "light", fontSize: 14, language: "en" };
const userPrefs = { theme: "dark", fontSize: 16 };
// Expected: { theme: "dark", fontSize: 16, language: "en" }
// Exercise 3: Destructuring
// Extract name and first hobby from this object
const person = {
name: "Alice",
hobbies: ["reading", "coding", "gaming"]
};
// Exercise 4: Data Transformation
// Convert this array of users to an object keyed by id
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" }
];
// Expected: { 1: { id: 1, name: "Alice" }, 2: {...}, 3: {...} }
Solutions
// Exercise 1
const doubled = numbers.filter(n => n % 2 === 0).map(n => n * 2);
// [4, 8, 12, 16, 20]
// Exercise 2
const merged = { ...defaults, ...userPrefs };
// { theme: "dark", fontSize: 16, language: "en" }
// Exercise 3
const { name, hobbies: [firstHobby] } = person;
// name = "Alice", firstHobby = "reading"
// Exercise 4
const usersById = users.reduce((acc, user) => {
acc[user.id] = user;
return acc;
}, {});
// { 1: { id: 1, name: "Alice" }, 2: {...}, 3: {...} }
Key Takeaways
- Arrays are ordered lists — use for sequences of items
- Objects are key-value pairs — use for named properties
- Destructuring simplifies extraction — cleaner code
- Spread operator enables immutable updates — don't mutate, create new
- map/filter/reduce are powerful — learn them well!
Module 04 Complete!
Congratulations! You've learned JavaScript basics:
- ✅ Variables and data types
- ✅ Functions and arrow functions
- ✅ Arrays and objects
Next Module
Ready to build your first project?