Month 1, Week 4

Core Data Structures & Functional Methods

Mastering Objects, Arrays, and the Art of Data Manipulation

Module 1: Deep Dive into Objects

The Building Blocks of Complex Data

Recap: What is an Object?

An object is a collection of related data and/or functionality. These consist of several variables and functions (which are called properties and methods when they are inside objects).

It's how we model real-world things, like a user, a product, or a server configuration.


                        const user = {
                            id: 'a1b2c3d4',
                            username: 'arch_dev',
                            email: 'architect@example.com',
                            isActive: true,
                            login: function() {
                                console.log(`${this.username} has logged in.`);
                            }
                        };
                    

Property Access: Dot vs. Bracket Notation

There are two ways to access an object's properties. Understanding when to use each is crucial.

Dot Notation (`.`)

Simple, clean, and the most common way.

console.log(user.username); // arch_dev

Limitation: The property name must be a valid JavaScript identifier and you must know it beforehand.

Bracket Notation (`[]`)

More powerful and flexible.


                                console.log(user['email']); // architect@example.com

                                const keyToAccess = 'isActive';
                                console.log(user[keyToAccess]); // true
                            

Use when: The property name is stored in a variable, or contains spaces or special characters.

Computed Property Names

You can use bracket notation during object creation to dynamically set property keys.


                        const role = 'admin';
                        const id = 123;

                        const user = {
                            [role]: 'Super User', // Property is named 'admin'
                            [`user_${id}`]: { status: 'active' } // Property is named 'user_123'
                        };

                        console.log(user.admin); // "Super User"
                        console.log(user.user_123.status); // "active"
                    

This is extremely useful when creating objects from dynamic data.

Module 2: Mastering Arrays

Ordered Collections of Data

What is an Array?

An array is a special type of object used for storing an ordered list of values. Each value is called an element, and each element has a numeric index, starting from zero.


                        // An array of strings
                        const roles = ['admin', 'editor', 'viewer'];

                        // An array of numbers
                        const accessLevels = [1, 2, 3, 4];

                        // An array of objects
                        const users = [
                            { id: 1, name: 'Alex' },
                            { id: 2, name: 'Jane' }
                        ];

                        // Accessing by index
                        console.log(roles[0]); // 'admin'
                        console.log(users[1].name); // 'Jane'
                    

Mutating Array Methods

These methods change the original array. Use them with care.

  • `.push(item)`: Adds an item to the **end**.
  • `.pop()`: Removes an item from the **end**.
  • `.unshift(item)`: Adds an item to the **beginning**.
  • `.shift()`: Removes an item from the **beginning**.
  • `.splice(startIndex, deleteCount, ...items)`: The swiss-army knife for adding/removing items anywhere.

                        const tasks = ['Code', 'Test'];
                        tasks.push('Deploy');    // ['Code', 'Test', 'Deploy']
                        tasks.shift();          // ['Test', 'Deploy']
                    

Mid-Lecture Knowledge Check

Module 3: Functional Array Methods

The Modern Way to Process Data

The Functional Mindset: Immutability

A core principle of functional programming is immutability. Instead of changing your original data, you create new data based on the original.

The methods we are about to see do not change the original array. They return a brand new array (or value).

This makes code safer, more predictable, and easier to debug.

`.forEach(callback)`: Just Looping

The simplest functional method. It executes a provided function once for each array element. It's a modern alternative to a basic `for` loop.

It does not return a new array; it always returns `undefined`.


                        const users = ['Alex', 'Jane', 'Peter'];

                        users.forEach(function(user, index) {
                            console.log(`User #${index + 1} is ${user}`);
                        });

                        // Output:
                        // User #1 is Alex
                        // User #2 is Jane
                        // User #3 is Peter
                    

`.map(callback)`: Transforming Data

The most important transformation method. It creates a new array populated with the results of calling a provided function on every element in the calling array.

Use it when you want to convert an array of one thing into an array of another thing.


                        const numbers = [1, 4, 9, 16];

                        // Create a new array of the square roots
                        const roots = numbers.map(function(num) {
                            return Math.sqrt(num);
                        });

                        console.log(roots);   // [1, 2, 3, 4]
                        console.log(numbers); // [1, 4, 9, 16] (Original is unchanged!)
                    

`.filter(callback)`: Selecting Data

Creates a new array with all elements that pass the test implemented by the provided function. The callback must return a boolean.

Use it when you want to select a subset of an array based on a condition.


                        const products = [
                            { name: 'Laptop', price: 1200, inStock: true },
                            { name: 'Mouse', price: 40, inStock: false },
                            { name: 'Keyboard', price: 100, inStock: true }
                        ];

                        const availableProducts = products.filter(function(product) {
                            return product.inStock === true;
                        });
                        // availableProducts is a new array with only the Laptop and Keyboard
                    

`.reduce(callback, initialValue)`: Aggregating Data

The most powerful but complex method. It executes a "reducer" function on each element of the array, resulting in a single output value.

Use it to "boil down" an array to one value (e.g., a sum, an object, a string).


                        const cart = [ { price: 10 }, { price: 25 }, { price: 15 } ];

                        // The `accumulator` is the value returned from the last iteration.
                        // The `currentItem` is the current element being processed.
                        // `0` is the initial value of the accumulator.
                        const total = cart.reduce(function(accumulator, currentItem) {
                            return accumulator + currentItem.price;
                        }, 0);

                        console.log(total); // 50
                     

`.find()`, `.some()`, `.every()`

These methods are for asking questions about your array.

  • `.find(callback)`: Returns the first element in the array that satisfies the provided testing function. If no values satisfy, `undefined` is returned.
  • `.some(callback)`: Tests whether at least one element in the array passes the test. Returns a boolean.
  • `.every(callback)`: Tests whether all elements in the array pass the test. Returns a boolean.

Chaining Methods: The Power Combo

The real power of functional methods comes from chaining them together. Because methods like `map` and `filter` return new arrays, you can immediately call another array method on the result.

This creates elegant, readable, and powerful data processing pipelines.


                        const users = [
                            { id: 1, name: 'Alex', role: 'admin', age: 30 },
                            { id: 2, name: 'Jane', role: 'editor', age: 25 },
                            { id: 3, name: 'Peter', role: 'admin', age: 42 }
                        ];

                        // Get the names of all admins over the age of 35, in uppercase.
                        const adminNames = users
                            .filter(user => user.role === 'admin')
                            .filter(admin => admin.age > 35)
                            .map(admin => admin.name.toUpperCase());

                        console.log(adminNames); // ['PETER']
                     

In-Class Practical Exercise

The Data Processing Pipeline

Your task is to use functional array methods to process a list of transactions and generate a report. This is a very common backend task.

  1. Create a new file `report.js`.
  2. Copy the provided `transactions` array.
  3. Write a single chain of commands to achieve the final goal.
  4. Use `console.log()` to print the final result.
  5. Run your script with `node report.js`.
The Goal:

Calculate the total amount from all successful debit transactions over $50, and return it as a formatted currency string.

Expected Output:
$270.00
Starter Code (`report.js`):

                            const transactions = [
                                { id: 't1', type: 'debit', status: 'success', amount: 150 },
                                { id: 't2', type: 'credit', status: 'success', amount: 200 },
                                { id: 't3', type: 'debit', status: 'failed', amount: 100 },
                                { id: 't4', type: 'debit', status: 'success', amount: 35 },
                                { id: 't5', type: 'debit', status: 'success', amount: 120 },
                            ];

                            // Your chained method solution goes here!
                            // const finalReport = transactions
                            //   .filter(...)
                            //   .filter(...)
                            //   .map(...)
                            //   .reduce(...);
                            //
                            // After reduce, format the final number.
                            // Hint: new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(number);
                            
                            // console.log(finalReport);
                         

Hint: You will need `filter` (twice), `map`, and `reduce`.

Final Knowledge Check

You are a Data Architect

You can now transform, select, and aggregate complex data with clarity and precision. This is a superpower.