4.4: Arrays & Objects
Learn how to work with arrays and objects to store and manipulate complex data in JavaScript. Master essential array methods, object properties, and techniques for accessing and modifying structured data.
1. Arrays
Creating Arrays
JavaScript:
// Array literal (most common)
const fruits = ["apple", "banana", "orange"];
// Array constructor (rarely used)
const numbers = new Array(1, 2, 3, 4, 5);
// Empty array
const empty = [];
// Mixed types (possible but not recommended)
const mixed = [1, "two", true, null, { name: "Alice" }];
Python comparison:
# Python list
fruits = ["apple", "banana", "orange"]
numbers = [1, 2, 3, 4, 5]
empty = []
mixed = [1, "two", True, None, {"name": "Alice"}]
Accessing Elements
const fruits = ["apple", "banana", "orange"];
// By index (0-based)
console.log(fruits[0]); // "apple"
console.log(fruits[1]); // "banana"
console.log(fruits[2]); // "orange"
// Negative indices NOT supported (unlike Python)
console.log(fruits[-1]); // undefined (not "orange")
// Get last element
console.log(fruits[fruits.length - 1]); // "orange"
// Array length
console.log(fruits.length); // 3
Python comparison:
fruits = ["apple", "banana", "orange"]
fruits[0] # "apple"
fruits[-1] # "orange" (negative indexing works!)
len(fruits) # 3
Modifying Arrays
Arrays are mutable:
const fruits = ["apple", "banana"];
// Add to end
fruits.push("orange"); // ["apple", "banana", "orange"]
// Remove from end
const last = fruits.pop(); // "orange", fruits = ["apple", "banana"]
// Add to beginning
fruits.unshift("mango"); // ["mango", "apple", "banana"]
// Remove from beginning
const first = fruits.shift(); // "mango", fruits = ["apple", "banana"]
// Modify by index
fruits[0] = "grape"; // ["grape", "banana"]
Python comparison:
fruits = ["apple", "banana"]
fruits.append("orange") # Add to end
fruits.pop() # Remove from end
fruits.insert(0, "mango") # Add to beginning
fruits.pop(0) # Remove from beginning
fruits[0] = "grape" # Modify by index
2. Array Methods
map() - Transform Each Element
Creates a new array by transforming each element:
const numbers = [1, 2, 3, 4, 5];
// Double each number
const doubled = numbers.map(x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// Extract property from objects
const users = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 }
];
const names = users.map(user => user.name);
console.log(names); // ["Alice", "Bob"]
Python comparison:
numbers = [1, 2, 3, 4, 5]
# Using map
doubled = list(map(lambda x: x * 2, numbers))
# List comprehension (more Pythonic)
doubled = [x * 2 for x in numbers]
filter() - Select Elements
Creates a new array with elements that pass a test:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Get even numbers
const evens = numbers.filter(x => x % 2 === 0);
console.log(evens); // [2, 4, 6, 8, 10]
// Filter objects
const users = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 17 },
{ name: "Charlie", age: 25 }
];
const adults = users.filter(user => user.age >= 18);
console.log(adults); // [{ name: "Alice", age: 30 }, { name: "Charlie", age: 25 }]
Python comparison:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Using filter
evens = list(filter(lambda x: x % 2 == 0, numbers))
# List comprehension
evens = [x for x in numbers if x % 2 == 0]
reduce() - Combine to Single Value
Reduces array to a single value:
const numbers = [1, 2, 3, 4, 5];
// Sum all numbers
const sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum); // 15
// Find max
const max = numbers.reduce((max, num) => num > max ? num : max, numbers[0]);
console.log(max); // 5
// Build object from array
const users = ["Alice", "Bob", "Charlie"];
const userObj = users.reduce((obj, name, index) => {
obj[index] = name;
return obj;
}, {});
console.log(userObj); // { 0: "Alice", 1: "Bob", 2: "Charlie" }
Python comparison:
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# Sum
total = reduce(lambda a, b: a + b, numbers, 0)
# Or built-in sum
total = sum(numbers)
find() and findIndex()
const numbers = [1, 2, 3, 4, 5];
// Find first element > 3
const found = numbers.find(x => x > 3);
console.log(found); // 4
// Find index of first element > 3
const index = numbers.findIndex(x => x > 3);
console.log(index); // 3
// Find object
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
];
const user = users.find(u => u.id === 2);
console.log(user); // { id: 2, name: "Bob" }
some() and every()
const numbers = [1, 2, 3, 4, 5];
// Check if ANY element is even
const hasEven = numbers.some(x => x % 2 === 0);
console.log(hasEven); // true
// Check if ALL elements are positive
const allPositive = numbers.every(x => x > 0);
console.log(allPositive); // true
Python comparison:
numbers = [1, 2, 3, 4, 5]
# some
has_even = any(x % 2 == 0 for x in numbers) # True
# every
all_positive = all(x > 0 for x in numbers) # True
includes() and indexOf()
const fruits = ["apple", "banana", "orange"];
// Check if array contains element
console.log(fruits.includes("banana")); // true
console.log(fruits.includes("grape")); // false
// Find index
console.log(fruits.indexOf("banana")); // 1
console.log(fruits.indexOf("grape")); // -1 (not found)
Python comparison:
fruits = ["apple", "banana", "orange"]
"banana" in fruits # True
fruits.index("banana") # 1
# fruits.index("grape") # Error: not in list
Slicing and Splicing
slice() - Extract portion (doesn't modify original):
const numbers = [1, 2, 3, 4, 5];
const sliced = numbers.slice(1, 3); // [2, 3]
const fromIndex = numbers.slice(2); // [3, 4, 5]
const lastTwo = numbers.slice(-2); // [4, 5]
console.log(numbers); // [1, 2, 3, 4, 5] (unchanged)
splice() - Modify original array:
const numbers = [1, 2, 3, 4, 5];
// Remove 2 elements starting at index 1
const removed = numbers.splice(1, 2);
console.log(removed); // [2, 3]
console.log(numbers); // [1, 4, 5]
// Insert elements
numbers.splice(1, 0, "a", "b"); // Insert at index 1
console.log(numbers); // [1, "a", "b", 4, 5]
// Replace elements
numbers.splice(1, 2, "x"); // Remove 2, insert "x"
console.log(numbers); // [1, "x", 4, 5]
Python comparison:
numbers = [1, 2, 3, 4, 5]
# Slicing (doesn't modify)
sliced = numbers[1:3] # [2, 3]
from_index = numbers[2:] # [3, 4, 5]
last_two = numbers[-2:] # [4, 5]
# Modifying requires del, insert, etc.
del numbers[1:3] # Remove elements
Other Useful Methods
const numbers = [3, 1, 4, 1, 5, 9, 2, 6];
// Sort (mutates original!)
numbers.sort();
console.log(numbers); // [1, 1, 2, 3, 4, 5, 6, 9]
// Sort with custom comparator
numbers.sort((a, b) => b - a); // Descending
console.log(numbers); // [9, 6, 5, 4, 3, 2, 1, 1]
// Reverse (mutates original!)
numbers.reverse();
console.log(numbers); // [1, 1, 2, 3, 4, 5, 6, 9]
// Join to string
const text = numbers.join(", ");
console.log(text); // "1, 1, 2, 3, 4, 5, 6, 9"
// Flat (flatten nested arrays)
const nested = [1, [2, 3], [4, [5, 6]]];
console.log(nested.flat()); // [1, 2, 3, 4, [5, 6]]
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6]
3. Array Destructuring
Extract values from arrays:
const colors = ["red", "green", "blue"];
// Old way
const first = colors[0];
const second = colors[1];
// Destructuring
const [r, g, b] = colors;
console.log(r); // "red"
console.log(g); // "green"
console.log(b); // "blue"
// Skip elements
const [, , third] = colors;
console.log(third); // "blue"
// Rest operator
const [primary, ...others] = colors;
console.log(primary); // "red"
console.log(others); // ["green", "blue"]
// Swap variables
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2, 1
Python comparison:
colors = ["red", "green", "blue"]
# Unpacking
r, g, b = colors
# Skip elements
_, _, third = colors
# Rest (Python 3.0+)
primary, *others = colors # primary = "red", others = ["green", "blue"]
# Swap
a, b = 1, 2
a, b = b, a
4. Objects
Creating Objects
// Object literal (most common)
const user = {
name: "Alice",
age: 30,
email: "alice@example.com"
};
// Empty object
const empty = {};
// Computed property names
const key = "dynamic";
const obj = {
[key]: "value",
[`${key}Key`]: "another value"
};
console.log(obj); // { dynamic: "value", dynamicKey: "another value" }
Python comparison:
# Python dictionary
user = {
"name": "Alice",
"age": 30,
"email": "alice@example.com"
}
empty = {}
Accessing Properties
const user = {
name: "Alice",
age: 30,
"favorite-color": "blue"
};
// Dot notation
console.log(user.name); // "Alice"
console.log(user.age); // 30
// Bracket notation (for dynamic keys or special characters)
console.log(user["name"]); // "Alice"
console.log(user["favorite-color"]); // "blue"
const key = "age";
console.log(user[key]); // 30
Python:
user = {
"name": "Alice",
"age": 30,
"favorite-color": "blue"
}
user["name"] # "Alice"
user.get("name") # "Alice" (safer)
user["favorite-color"] # "blue"
key = "age"
user[key] # 30
Modifying Objects
const user = {
name: "Alice",
age: 30
};
// Add property
user.email = "alice@example.com";
user["phone"] = "555-1234";
// Modify property
user.age = 31;
// Delete property
delete user.phone;
console.log(user);
// { name: "Alice", age: 31, email: "alice@example.com" }
Object Methods
const user = {
name: "Alice",
age: 30,
greet() {
return `Hello, I'm ${this.name}`;
},
// Arrow function (careful with 'this'!)
sayAge: () => {
// return `I'm ${this.age}`; // Won't work! Arrow has no 'this'
}
};
console.log(user.greet()); // "Hello, I'm Alice"
Python comparison:
class User:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return f"Hello, I'm {self.name}"
user = User("Alice", 30)
user.greet() # "Hello, I'm Alice"
Object Iteration
const user = {
name: "Alice",
age: 30,
city: "NYC"
};
// Get keys
const keys = Object.keys(user);
console.log(keys); // ["name", "age", "city"]
// Get values
const values = Object.values(user);
console.log(values); // ["Alice", 30, "NYC"]
// Get entries (key-value pairs)
const entries = Object.entries(user);
console.log(entries);
// [["name", "Alice"], ["age", 30], ["city", "NYC"]]
// Iterate
for (const key in user) {
console.log(key, user[key]);
}
// Better: Object.entries()
for (const [key, value] of Object.entries(user)) {
console.log(key, value);
}
Python comparison:
user = {"name": "Alice", "age": 30, "city": "NYC"}
user.keys() # dict_keys(["name", "age", "city"])
user.values() # dict_values(["Alice", 30, "NYC"])
user.items() # dict_items([("name", "Alice"), ...])
for key, value in user.items():
print(key, value)
5. Object Destructuring
const user = {
name: "Alice",
age: 30,
city: "NYC"
};
// Destructuring
const { name, age } = user;
console.log(name); // "Alice"
console.log(age); // 30
// Rename variables
const { name: userName, age: userAge } = user;
console.log(userName); // "Alice"
// Default values
const { country = "USA" } = user;
console.log(country); // "USA"
// Rest operator
const { name: n, ...rest } = user;
console.log(n); // "Alice"
console.log(rest); // { age: 30, city: "NYC" }
// Nested destructuring
const data = {
user: {
name: "Alice",
address: {
city: "NYC"
}
}
};
const { user: { name: userName2, address: { city } } } = data;
console.log(userName2); // "Alice"
console.log(city); // "NYC"
Function parameter destructuring:
function greet({ name, age }) {
return `Hello ${name}, you are ${age} years old`;
}
const user = { name: "Alice", age: 30, city: "NYC" };
console.log(greet(user)); // "Hello Alice, you are 30 years old"
6. Spread and Rest with Objects
Spread Operator
Copy and merge objects:
const user = { name: "Alice", age: 30 };
// Shallow copy
const copy = { ...user };
// Merge objects
const address = { city: "NYC", country: "USA" };
const fullUser = { ...user, ...address };
console.log(fullUser);
// { name: "Alice", age: 30, city: "NYC", country: "USA" }
// Override properties
const updated = { ...user, age: 31 };
console.log(updated); // { name: "Alice", age: 31 }
Python comparison:
user = {"name": "Alice", "age": 30}
# Copy (shallow)
copy = user.copy()
# Or
copy = {**user}
# Merge
address = {"city": "NYC", "country": "USA"}
full_user = {**user, **address}
# Override
updated = {**user, "age": 31}
Rest Operator
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
// With destructuring
const { name, ...otherProps } = { name: "Alice", age: 30, city: "NYC" };
console.log(name); // "Alice"
console.log(otherProps); // { age: 30, city: "NYC" }
7. JSON (JavaScript Object Notation)
JSON.stringify() - Object to String
const user = {
name: "Alice",
age: 30,
active: true
};
const json = JSON.stringify(user);
console.log(json); // '{"name":"Alice","age":30,"active":true}'
// Pretty print
const prettyJson = JSON.stringify(user, null, 2);
console.log(prettyJson);
/*
{
"name": "Alice",
"age": 30,
"active": true
}
*/
Python comparison:
import json
user = {"name": "Alice", "age": 30, "active": True}
# To JSON string
json_str = json.dumps(user)
# Pretty print
pretty = json.dumps(user, indent=2)
JSON.parse() - String to Object
const jsonString = '{"name":"Alice","age":30}';
const user = JSON.parse(jsonString);
console.log(user.name); // "Alice"
console.log(user.age); // 30
Python:
import json
json_str = '{"name":"Alice","age":30}'
user = json.loads(json_str)
user["name"] # "Alice"
8. Practical Examples
Example 1: Data Transformation
const users = [
{ id: 1, name: "Alice", age: 30, active: true },
{ id: 2, name: "Bob", age: 25, active: false },
{ id: 3, name: "Charlie", age: 35, active: true }
];
// Get active users' names
const activeNames = users
.filter(u => u.active)
.map(u => u.name);
console.log(activeNames); // ["Alice", "Charlie"]
// Average age
const avgAge = users.reduce((sum, u) => sum + u.age, 0) / users.length;
console.log(avgAge); // 30
Example 2: Group By
const products = [
{ name: "Apple", category: "Fruit" },
{ name: "Carrot", category: "Vegetable" },
{ name: "Banana", category: "Fruit" },
{ name: "Broccoli", category: "Vegetable" }
];
const grouped = products.reduce((acc, item) => {
const { category } = item;
if (!acc[category]) {
acc[category] = [];
}
acc[category].push(item);
return acc;
}, {});
console.log(grouped);
/*
{
Fruit: [{ name: "Apple", ... }, { name: "Banana", ... }],
Vegetable: [{ name: "Carrot", ... }, { name: "Broccoli", ... }]
}
*/
Example 3: Deep Clone
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
const original = {
name: "Alice",
address: { city: "NYC" }
};
const clone = deepClone(original);
clone.address.city = "LA";
console.log(original.address.city); // "NYC" (unchanged)
console.log(clone.address.city); // "LA"
9. Practical Exercises
Exercise 4.4.1: Array Methods Chain
Given an array of numbers, use method chaining to:
- Filter for numbers > 10
- Square each number
- Sum the results
Exercise 4.4.2: Object Manipulation
Create a function that:
- Takes an array of user objects
- Returns an object keyed by user ID
- Each value contains only name and email
Exercise 4.4.3: Destructuring Practice
Rewrite using destructuring:
function getFullName(user) {
return user.firstName + " " + user.lastName;
}
Exercise 4.4.4: Data Processing
Process this data to get unique categories:
const items = [
{ name: "Item 1", category: "A" },
{ name: "Item 2", category: "B" },
{ name: "Item 3", category: "A" }
];
10. Knowledge Check
Question 1: What's the difference between map() and forEach()?
Show answer
map() returns a new array with transformed elements. forEach() just iterates and returns undefined. Use map() for transformations, forEach() for side effects.Question 2: When should you use bracket notation vs dot notation?
Show answer
Use bracket notation for: dynamic keys (variables), special characters in keys, or property names that are reserved words. Otherwise use dot notation.Question 3: What does the spread operator do with objects?
Show answer
Spreads object properties into a new object. Creates shallow copy and allows merging: `{...obj1, ...obj2}`.Question 4: What's the difference between slice() and splice()?
Show answer
slice() extracts portion without modifying original. splice() modifies original array by removing/inserting elements.11. Key Takeaways
- Arrays are ordered, zero-indexed collections
- Use map(), filter(), reduce() for transformations
- find(), some(), every() for searching
- slice() extracts, splice() modifies
- Objects store key-value pairs
- Access properties with dot (obj.key) or bracket (objkey)
- Object.keys/values/entries() for iteration
- Destructuring extracts values:
const {name} = obj - Spread copies/merges:
{...obj}or[...arr] - JSON.stringify() → string, JSON.parse() → object
12. Further Resources
Documentation:
Next Steps
Excellent work! You now master JavaScript's core data structures.
In Lesson 4.5: DOM Manipulation, you'll learn to interact with HTML elements using JavaScript to create dynamic web pages.
Next: Lesson 4.5 - DOM Manipulation →