Arrays and Objects (Core Web3 Skill)

JavaScript... Lesson 3 of 5 14 min

JavaScript Foundations

Day 3: Arrays & Objects - Handling Structured Data for Web3 Development

Welcome to Day 3: The Web3 Essential

So far, you've worked with individual values single numbers, strings, and booleans. But real-world applications, especially blockchain and Web3 development, deal with collections of data. Think about it: a blockchain is essentially a massive array of blocks, each containing transaction objects.

Today you'll master Arrays (ordered lists) and Objects (key-value collections). These are the fundamental data structures that power everything from NFT metadata to DeFi transaction histories. This is the most critical day for your Web3 journey.

Today's Goal: Master structured data handling. By the end, you'll manipulate arrays of objects, use powerful array methods like .map() and .filter(), and build functions that analyze complex datasets—exactly what you'll do with blockchain data.

Why This Matters for Web3

Blockchain Transactions
Array of objects: Each block contains transactions with properties like from, to, amount, timestamp
NFT Metadata
Object: Properties like name, image, attributes array describing traits
Token Balances
Array of objects: Wallet addresses mapped to token amounts, requiring filtering and mapping

Arrays: Ordered Collections

An array is an ordered list of values. Think of it as a row of boxes, each with a number (index) starting from 0. Arrays can hold any type of data—numbers, strings, objects, even other arrays.

Creating Arrays

// Creating arrays
const numbers = [1, 2, 3, 4, 5];
const fruits = ["apple", "banana", "orange"];
const mixed = [1, "hello", true, null];

// Empty array
const empty = [];

// Array of objects (Web3 style!)
const transactions = [
    { from: "0x123...", to: "0x456...", amount: 1.5 },
    { from: "0x789...", to: "0xabc...", amount: 0.5 }
];

Visual Memory Representation:

const fruits = ["apple", "banana", "orange"];
Index 0
"apple"
Index 1
"banana"
Index 2
"orange"

Arrays are zero-indexed: first item is at position 0

Accessing Array Elements

const colors = ["red", "green", "blue", "yellow"];

// Access by index (starts at 0!)
console.log(colors[0]);  // "red"
console.log(colors[1]);  // "green"
console.log(colors[2]);  // "blue"

// Get the last element
console.log(colors[colors.length - 1]);  // "yellow"

// Modify an element
colors[1] = "purple";
console.log(colors);  // ["red", "purple", "blue", "yellow"]

Access Visualization:

[0]
"red"
[1]
"green"
[2]
"blue"
[3]
"yellow"
colors[1] "green"

Array Properties and Basic Methods

const numbers = [10, 20, 30];

// Length property
console.log(numbers.length);  // 3

// push() - Add to end
numbers.push(40);
console.log(numbers);  // [10, 20, 30, 40]

// pop() - Remove from end
const last = numbers.pop();
console.log(last);     // 40
console.log(numbers);  // [10, 20, 30]

// unshift() - Add to beginning
numbers.unshift(5);
console.log(numbers);  // [5, 10, 20, 30]

// shift() - Remove from beginning
const first = numbers.shift();
console.log(first);    // 5

Visual Stack Operations:

push(40): Add to end
10
20
30
40
pop(): Remove from end
10
20
30
40 removed

Objects: Key-Value Collections

While arrays store ordered lists, objects store named properties. Each value has a key (name) that describes it. This is how real-world entities are modeled in code—perfect for representing blockchain transactions, user profiles, or NFT metadata.

Creating Objects

// Object with properties
const user = {
    name: "Joshua",
    age: 25,
    isStudent: false,
    wallet: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
};

// Web3 transaction object
const transaction = {
    hash: "0xabc123...",
    from: "0x111...",
    to: "0x222...",
    value: 1.5,
    gas: 21000,
    timestamp: 1640995200
};

// Nested objects
const nft = {
    name: "Crypto Punk #1234",
    image: "https://...",
    attributes: {
        rarity: "legendary",
        type: "human",
        accessories: ["sunglasses", "hat"]
    }
};

Object Structure Visualization:

const user = { ... }
"name" : "Joshua"
"age" : 25
"isStudent" : false
"wallet" : "0x742d..."

Keys are strings, values can be any type

Accessing Object Properties

const wallet = {
    address: "0x742d...",
    balance: 1.5,
    chain: "Ethereum"
};

// Dot notation (most common)
console.log(wallet.address);   // "0x742d..."
console.log(wallet.balance);   // 1.5

// Bracket notation (useful for dynamic keys)
console.log(wallet["chain"]);  // "Ethereum"

const key = "balance";
console.log(wallet[key]);      // 1.5

// Modifying properties
wallet.balance = 2.0;
wallet.token = "ETH";          // Add new property

console.log(wallet);
// { address: "0x742d...", balance: 2.0, chain: "Ethereum", token: "ETH" }

Access Methods Compared:

Dot Notation
wallet.balance
✓ Clean and readable
✓ Most common
Bracket Notation
wallet["balance"]
✓ Dynamic keys
✓ Special characters

Arrays of Objects: The Web3 Standard

This is the most common data structure in Web3 development. Every API returns arrays of objects—transactions, tokens, NFTs, etc.

// Array of user objects
const users = [
    { name: "Joshua", score: 80, wallet: "0x111..." },
    { name: "David", score: 45, wallet: "0x222..." },
    { name: "Sarah", score: 92, wallet: "0x333..." },
    { name: "Mike", score: 67, wallet: "0x444..." }
];

// Accessing nested data
console.log(users[0].name);        // "Joshua"
console.log(users[1].score);       // 45
console.log(users[2].wallet);      // "0x333..."

// Array of blockchain transactions
const transactions = [
    { 
        hash: "0xabc...", 
        from: "0x123...", 
        to: "0x456...", 
        value: 1.5,
        confirmed: true 
    },
    { 
        hash: "0xdef...", 
        from: "0x789...", 
        to: "0xabc...", 
        value: 0.5,
        confirmed: false 
    }
];

console.log(transactions[0].value);     // 1.5
console.log(transactions[1].confirmed); // false

Visual Structure:

const users = [ ... ]
[0] { name: "Joshua", score: 80, wallet: "0x111..." }
[1] { name: "David", score: 45, wallet: "0x222..." }
[2] { name: "Sarah", score: 92, wallet: "0x333..." }

Each array element is an object with multiple properties

Powerful Array Methods

Modern JavaScript provides powerful methods to transform, filter, and analyze arrays. These are essential for processing blockchain data, filtering transactions, and transforming API responses.

.map() - Transform Each Element

Creates a new array by applying a function to every element. Perfect for extracting specific properties or transforming data formats.

const users = [
    { name: "Joshua", score: 80 },
    { name: "David", score: 45 },
    { name: "Sarah", score: 92 }
];

// Extract just the names
const names = users.map(user => user.name);
console.log(names);  // ["Joshua", "David", "Sarah"]

// Extract scores with bonus
const finalScores = users.map(user => user.score + 5);
console.log(finalScores);  // [85, 50, 97]

// Create formatted strings
const summaries = users.map(user => 
    `${user.name} scored ${user.score}`
);
console.log(summaries);
// ["Joshua scored 80", "David scored 45", "Sarah scored 92"]

How .map() Works:

Original Array:
{name: "Joshua", score: 80}
{name: "David", score: 45}
{name: "Sarah", score: 92}
↓ .map(user => user.name)
New Array:
"Joshua"
"David"
"Sarah"

.filter() - Select Specific Elements

Creates a new array with only elements that pass a test. Essential for finding passing students, confirmed transactions, or specific token types.

const users = [
    { name: "Joshua", score: 80 },
    { name: "David", score: 45 },
    { name: "Sarah", score: 92 },
    { name: "Mike", score: 67 }
];

// Find passing students (score >= 50)
const passing = users.filter(user => user.score >= 50);
console.log(passing);
// [{ name: "Joshua", score: 80 }, { name: "Sarah", score: 92 }, { name: "Mike", score: 67 }]

// Find failing students
const failing = users.filter(user => user.score < 50);
console.log(failing);
// [{ name: "David", score: 45 }]

// Get just names of passing students
const passingNames = users
    .filter(user => user.score >= 50)
    .map(user => user.name);
console.log(passingNames);  // ["Joshua", "Sarah", "Mike"]

Filter Visualization:

All Students:
Joshua: 80 ✓ (>= 50)
David: 45 ✗ (< 50)
Sarah: 92 ✓ (>= 50)
Mike: 67 ✓ (>= 50)
↓ .filter(score >= 50)
Passing Students:
Joshua: 80
Sarah: 92
Mike: 67

.find() - Get First Match

Returns the first element that matches a condition. Perfect for finding a specific user, transaction, or token.

const users = [
    { name: "Joshua", score: 80, id: 1 },
    { name: "David", score: 45, id: 2 },
    { name: "Sarah", score: 92, id: 3 }
];

// Find user by name
const joshua = users.find(user => user.name === "Joshua");
console.log(joshua);  // { name: "Joshua", score: 80, id: 1 }

// Find first user with score > 90
const topStudent = users.find(user => user.score > 90);
console.log(topStudent);  // { name: "Sarah", score: 92, id: 3 }

// Find by ID (common in Web3)
const userById = users.find(user => user.id === 2);
console.log(userById);  // { name: "David", score: 45, id: 2 }

.forEach() - Loop Through Array

Executes a function for each element. Use when you want to perform an action (like console.log) rather than create a new array.

const users = [
    { name: "Joshua", score: 80 },
    { name: "David", score: 45 },
    { name: "Sarah", score: 92 }
];

// Print each user's status
users.forEach(user => {
    const status = user.score >= 50 ? "PASSED" : "FAILED";
    console.log(`${user.name}: ${status}`);
});

// Output:
// Joshua: PASSED
// David: FAILED
// Sarah: PASSED

Practical Web3 Examples

Let's build the exact skills you'll use daily in blockchain development.

Example 1: Student Pass/Fail System

Loop through users and print who passed (score >= 50).

const users = [
    { name: "Joshua", score: 80 },
    { name: "David", score: 45 },
    { name: "Sarah", score: 92 },
    { name: "Mike", score: 67 }
];

console.log("=== EXAM RESULTS ===");

// Method 1: Using forEach
users.forEach(user => {
    if (user.score >= 50) {
        console.log(`✓ ${user.name}: PASSED (${user.score}%)`);
    } else {
        console.log(`✗ ${user.name}: FAILED (${user.score}%)`);
    }
});

// Method 2: Using filter and forEach (functional approach)
console.log("\n--- PASSED STUDENTS ---");
users
    .filter(user => user.score >= 50)
    .forEach(user => console.log(`✓ ${user.name}: ${user.score}%`));

console.log("\n--- FAILED STUDENTS ---");
users
    .filter(user => user.score < 50)
    .forEach(user => console.log(`✗ ${user.name}: ${user.score}%`));

Expected Output:

=== EXAM RESULTS ===
✓ Joshua: PASSED (80%)
✗ David: FAILED (45%)
✓ Sarah: PASSED (92%)
✓ Mike: PASSED (67%)

--- PASSED STUDENTS ---
✓ Joshua: 80%
✓ Sarah: 92%
✓ Mike: 67%

--- FAILED STUDENTS ---
✗ David: 45%

Example 2: Find Highest Score

Create a function that finds the highest score in an array of users.

const users = [
    { name: "Joshua", score: 80 },
    { name: "David", score: 45 },
    { name: "Sarah", score: 92 },
    { name: "Mike", score: 67 }
];

// Method 1: Using a loop (imperative)
function findHighestScore(users) {
    if (users.length === 0) return null;
    
    let highest = users[0];  // Start with first user
    
    for (let i = 1; i < users.length; i++) {
        if (users[i].score > highest.score) {
            highest = users[i];  // Found new highest
        }
    }
    
    return highest;
}

// Method 2: Using reduce (functional)
function findHighestScoreReduce(users) {
    return users.reduce((max, user) => 
        user.score > max.score ? user : max
    );
}

// Method 3: Sort and take first (simple but less efficient)
function findHighestScoreSort(users) {
    return [...users].sort((a, b) => b.score - a.score)[0];
}

// Test
const topStudent = findHighestScore(users);
console.log(`Top student: ${topStudent.name} with ${topStudent.score}%`);
// Output: Top student: Sarah with 92%

Algorithm Visualization (Loop Method):

Initial State:
highest = { name: "Joshua", score: 80 }
Iteration 1 (David: 45):
45 > 80? NO → Keep Joshua
Iteration 2 (Sarah: 92):
92 > 80? YES → Update highest to Sarah
Iteration 3 (Mike: 67):
67 > 92? NO → Keep Sarah
Result: Sarah with 92%

Example 3: Blockchain Transaction Analyzer

Real-world Web3 example: Analyze an array of transaction objects.

const transactions = [
    { hash: "0x1", from: "Alice", to: "Bob", value: 1.5, confirmed: true },
    { hash: "0x2", from: "Bob", to: "Charlie", value: 0.5, confirmed: false },
    { hash: "0x3", from: "Alice", to: "David", value: 2.0, confirmed: true },
    { hash: "0x4", from: "Charlie", to: "Alice", value: 1.0, confirmed: true }
];

// 1. Get all confirmed transactions
const confirmed = transactions.filter(tx => tx.confirmed);
console.log("Confirmed:", confirmed.length);

// 2. Calculate total value of confirmed transactions
const totalValue = confirmed.reduce((sum, tx) => sum + tx.value, 0);
console.log("Total value:", totalValue);

// 3. Get all unique senders
const senders = [...new Set(transactions.map(tx => tx.from))];
console.log("Senders:", senders);

// 4. Find transaction by hash
const findTx = hash => transactions.find(tx => tx.hash === hash);
console.log("Find 0x3:", findTx("0x3"));

// 5. Get Alice's outgoing transactions
const aliceOutgoing = transactions.filter(tx => tx.from === "Alice");
console.log("Alice sent:", aliceOutgoing);

Data Flow Visualization:

Raw Transactions (4 items)
0x1: Alice→Bob, 1.5 ETH ✓
0x2: Bob→Charlie, 0.5 ETH ✗
0x3: Alice→David, 2.0 ETH ✓
0x4: Charlie→Alice, 1.0 ETH ✓
.filter(confirmed)
3 transactions
Removes unconfirmed
.reduce(sum)
4.5 ETH total
1.5 + 2.0 + 1.0
.map(from)
[Alice, Bob, Alice, Charlie]
Extract senders
new Set()
[Alice, Bob, Charlie]
Unique values only

Hands-On Exercises

Create day3-practice.js and build these essential skills.

Exercise 1: NFT Collection Analyzer

Task: Analyze an array of NFT objects.

const nfts = [
    { id: 1, name: "Crypto Punk", price: 2.5, owner: "0x123" },
    { id: 2, name: "Bored Ape", price: 8.0, owner: "0x456" },
    { id: 3, name: "Doodle", price: 1.2, owner: "0x123" },
    { id: 4, name: "Azuki", price: 5.5, owner: "0x789" }
];

// 1. Get all NFT names
const names = nfts.map(nft => nft.name);
console.log("Names:", names);

// 2. Find NFTs owned by 0x123
const ownedBy123 = nfts.filter(nft => nft.owner === "0x123");
console.log("Owned by 0x123:", ownedBy123);

// 3. Calculate total value of collection
const totalValue = nfts.reduce((sum, nft) => sum + nft.price, 0);
console.log("Total value:", totalValue, "ETH");

// 4. Find most expensive NFT
const mostExpensive = nfts.reduce((max, nft) => 
    nft.price > max.price ? nft : max
);
console.log("Most expensive:", mostExpensive.name);

Exercise 2: Token Balance Tracker

Task: Track token balances and calculate totals.

const balances = [
    { token: "ETH", amount: 1.5, priceUSD: 2000 },
    { token: "USDC", amount: 500, priceUSD: 1 },
    { token: "LINK", amount: 100, priceUSD: 15 },
    { token: "ETH", amount: 0.5, priceUSD: 2000 }  // More ETH
];

// 1. Calculate USD value of each holding
const withValues = balances.map(b => ({
    ...b,
    valueUSD: b.amount * b.priceUSD
}));
console.log(withValues);

// 2. Find all ETH holdings
const ethHoldings = balances.filter(b => b.token === "ETH");
console.log("ETH holdings:", ethHoldings);

// 3. Calculate total portfolio value
const totalUSD = withValues.reduce((sum, b) => sum + b.valueUSD, 0);
console.log("Total portfolio:", totalUSD, "USD");

// 4. Group by token type (advanced)
const grouped = balances.reduce((acc, b) => {
    acc[b.token] = (acc[b.token] || 0) + b.amount;
    return acc;
}, {});
console.log("Grouped:", grouped);

Exercise 3: Complete Student System

Task: Build the complete pass/fail system with highest score finder.

const users = [
    { name: "Joshua", score: 80 },
    { name: "David", score: 45 },
    { name: "Sarah", score: 92 },
    { name: "Mike", score: 67 },
    { name: "Emma", score: 95 }
];

// Function: Print pass/fail status
function printResults(students) {
    console.log("=== EXAM RESULTS ===");
    students.forEach(student => {
        const status = student.score >= 50 ? "✓ PASSED" : "✗ FAILED";
        console.log(`${status}: ${student.name} (${student.score}%)`);
    });
}

// Function: Find highest score
function findHighestScore(students) {
    return students.reduce((highest, student) => 
        student.score > highest.score ? student : highest
    );
}

// Function: Get passing students
function getPassingStudents(students) {
    return students.filter(s => s.score >= 50);
}

// Function: Calculate average score
function calculateAverage(students) {
    const total = students.reduce((sum, s) => sum + s.score, 0);
    return total / students.length;
}

// Run analysis
printResults(users);

const topStudent = findHighestScore(users);
console.log(`\n🏆 Top Student: ${topStudent.name} with ${topStudent.score}%`);

const passing = getPassingStudents(users);
console.log(`\n📊 Passing: ${passing.length}/${users.length} students`);

const average = calculateAverage(users);
console.log(`📈 Average Score: ${average.toFixed(1)}%`);

Expected Output:

=== EXAM RESULTS ===
✓ PASSED: Joshua (80%)
✗ FAILED: David (45%)
✓ PASSED: Sarah (92%)
✓ PASSED: Mike (67%)
✓ PASSED: Emma (95%)

🏆 Top Student: Emma with 95%

📊 Passing: 4/5 students
📈 Average Score: 75.8%

Complete Practice File

// ===================================
// JavaScript Day 3: Arrays & Objects
// Web3 Data Handling Mastery
// ===================================

// Exercise 1: Basic Array Operations
console.log("=== ARRAY BASICS ===");
const tokens = ["ETH", "USDC", "LINK", "UNI"];
console.log("First token:", tokens[0]);
console.log("Total tokens:", tokens.length);

tokens.push("AAVE");
console.log("After push:", tokens);

const last = tokens.pop();
console.log("Popped:", last);
console.log("");

// Exercise 2: Object Creation & Access
console.log("=== OBJECT BASICS ===");
const wallet = {
    address: "0x742d...",
    ethBalance: 2.5,
    isConnected: true,
    tokens: ["ETH", "USDC"]
};
console.log("Address:", wallet.address);
console.log("ETH:", wallet.ethBalance);
wallet.ethBalance = 3.0;  // Update
console.log("Updated ETH:", wallet.ethBalance);
console.log("");

// Exercise 3: Array of Objects (The Web3 Standard)
console.log("=== ARRAY OF OBJECTS ===");
const transactions = [
    { hash: "0x1", from: "Alice", to: "Bob", value: 1.5 },
    { hash: "0x2", from: "Bob", to: "Charlie", value: 0.5 },
    { hash: "0x3", from: "Alice", to: "David", value: 2.0 }
];

// Access nested data
console.log("Tx 1 from:", transactions[0].from);
console.log("Tx 2 value:", transactions[1].value);
console.log("");

// Exercise 4: .map() Transformation
console.log("=== MAP TRANSFORMATIONS ===");
const txValues = transactions.map(tx => tx.value);
console.log("All values:", txValues);

const txSummaries = transactions.map(tx => 
    `${tx.from} sent ${tx.value} ETH to ${tx.to}`
);
console.log("Summaries:", txSummaries);
console.log("");

// Exercise 5: .filter() Selection
console.log("=== FILTER OPERATIONS ===");
const bigTxs = transactions.filter(tx => tx.value > 1.0);
console.log("Big transactions:", bigTxs);

const aliceTxs = transactions.filter(tx => tx.from === "Alice");
console.log("Alice's transactions:", aliceTxs);
console.log("");

// Exercise 6: .find() Specific Item
console.log("=== FIND OPERATIONS ===");
const tx0x2 = transactions.find(tx => tx.hash === "0x2");
console.log("Found tx:", tx0x2);
console.log("");

// Exercise 7: .reduce() Aggregation
console.log("=== REDUCE OPERATIONS ===");
const totalVolume = transactions.reduce((sum, tx) => sum + tx.value, 0);
console.log("Total volume:", totalVolume, "ETH");
console.log("");

// Exercise 8: Student Grade System
console.log("=== STUDENT GRADE SYSTEM ===");
const students = [
    { name: "Joshua", score: 80 },
    { name: "David", score: 45 },
    { name: "Sarah", score: 92 },
    { name: "Mike", score: 67 }
];

// Print pass/fail
students.forEach(s => {
    const status = s.score >= 50 ? "PASSED" : "FAILED";
    console.log(`${s.name}: ${status} (${s.score}%)`);
});

// Find highest score
const top = students.reduce((max, s) => s.score > max.score ? s : max);
console.log(`\nHighest score: ${top.name} (${top.score}%)`);

// Get passing students
const passed = students.filter(s => s.score >= 50);
console.log(`Passing students: ${passed.map(s => s.name).join(", ")}`);

Testing Checklist

✓ Create day3-practice.js
✓ Link in HTML before closing body tag
✓ Open browser → F12 → Console tab
✓ Verify all outputs match expected results
✓ Modify data and observe changes

Complete this lesson

Mark as complete to track your progress