Introduction to JavaScript · Lesson 2 of 5

Arrays & Objects

JavaScript Arrays and Objects

Arrays and objects are the two data structures you'll use in every JavaScript program. This lesson covers both deeply, including modern ES6+ patterns.


Arrays

Creating Arrays

JavaScript
const fruits = ["apple", "banana", "cherry"];
const numbers = [1, 2, 3, 4, 5];
const mixed = [1, "hello", true, null, { id: 1 }];
const empty = [];
const fromLength = new Array(3);       // [empty × 3]
const filled = new Array(3).fill(0);   // [0, 0, 0]

Accessing and Modifying

JavaScript
const arr = ["a", "b", "c", "d"];

arr[0]       // "a"
arr[arr.length - 1] // "d" — last element
arr.at(-1)   // "d" — modern way to get last element
arr.at(-2)   // "c"

// Mutating methods (change the original array)
arr.push("e");          // add to end: ["a","b","c","d","e"]
arr.pop();              // remove from end, returns "e": ["a","b","c","d"]
arr.unshift("z");       // add to start: ["z","a","b","c","d"]
arr.shift();            // remove from start, returns "z": ["a","b","c","d"]
arr.splice(1, 1);       // remove 1 element at index 1: ["a","c","d"]
arr.splice(1, 0, "X");  // insert "X" at index 1: ["a","X","c","d"]
arr.reverse();          // reverses in place
arr.sort();             // sorts in place (lexicographic by default)
arr.sort((a, b) => a - b); // sort numbers numerically

The Functional Array Methods

These are the methods you'll use most as a modern JS developer. They all return new arrays (non-mutating).

filter — keep matching elements

JavaScript
const products = [
  { name: "Laptop", price: 999, inStock: true },
  { name: "Mouse", price: 25, inStock: false },
  { name: "Keyboard", price: 79, inStock: true },
  { name: "Monitor", price: 349, inStock: true },
];

const available = products.filter(p => p.inStock);
// [Laptop, Keyboard, Monitor]

const affordable = products.filter(p => p.price < 100 && p.inStock);
// [Keyboard]

map — transform every element

JavaScript
const prices = products.map(p => p.price);
// [999, 25, 79, 349]

const withTax = products.map(p => ({
  ...p,
  priceWithTax: (p.price * 1.2).toFixed(2)
}));
// adds priceWithTax to each product object

reduce — collapse to a single value

JavaScript
// Sum all prices
const total = products.reduce((sum, p) => sum + p.price, 0);
// 1452

// Group by in-stock status
const grouped = products.reduce((acc, p) => {
  const key = p.inStock ? "available" : "outOfStock";
  acc[key] = acc[key] || [];
  acc[key].push(p);
  return acc;
}, {});
// { available: [...], outOfStock: [...] }

find, findIndex, some, every

JavaScript
const laptop = products.find(p => p.name === "Laptop");
// { name: "Laptop", price: 999, inStock: true }

const laptopIndex = products.findIndex(p => p.name === "Laptop");
// 0

const hasExpensive = products.some(p => p.price > 500);   // true
const allInStock = products.every(p => p.inStock);        // false

flat, flatMap

JavaScript
const nested = [[1, 2], [3, 4], [5, 6]];
nested.flat();       // [1, 2, 3, 4, 5, 6]
nested.flat(2);      // flattens 2 levels deep

// flatMap = map + flat(1)
const sentences = ["hello world", "foo bar"];
sentences.flatMap(s => s.split(" "));
// ["hello", "world", "foo", "bar"]

Chaining methods

JavaScript
const result = products
  .filter(p => p.inStock)
  .map(p => ({ name: p.name, price: p.price }))
  .sort((a, b) => a.price - b.price);
// sorted available products, cheapest first

Array Spread and Destructuring

JavaScript
// Spread — copy or merge arrays
const a = [1, 2, 3];
const b = [4, 5, 6];
const merged = [...a, ...b];        // [1,2,3,4,5,6]
const copy = [...a];                 // shallow copy
const prepended = [0, ...a];        // [0,1,2,3]

// Destructuring — extract values into variables
const [first, second, ...rest] = [10, 20, 30, 40, 50];
first;  // 10
second; // 20
rest;   // [30, 40, 50]

// Skip elements
const [,, third] = [10, 20, 30];
third; // 30

// Default values
const [x = 0, y = 0] = [5];
x; // 5
y; // 0 (default used)

// Swap variables
let p = 1, q = 2;
[p, q] = [q, p];
p; // 2, q; // 1

Objects

Creating Objects

JavaScript
// Object literal
const user = {
  id: 1,
  name: "Asma",
  email: "asma@example.com",
  isActive: true
};

// Shorthand properties (when variable name === key name)
const name = "Asma";
const age = 30;
const person = { name, age };  // { name: "Asma", age: 30 }

// Computed property names
const key = "dynamicKey";
const obj = { [key]: "value" };  // { dynamicKey: "value" }

// Methods
const calculator = {
  value: 0,
  add(n) { this.value += n; return this; },
  subtract(n) { this.value -= n; return this; },
  result() { return this.value; }
};
calculator.add(10).add(5).subtract(3).result(); // 12

Accessing Properties

JavaScript
const user = { name: "Asma", address: { city: "Oslo", country: "Norway" } };

// Dot notation
user.name;             // "Asma"
user.address.city;     // "Oslo"

// Bracket notation (for dynamic keys or keys with spaces)
user["name"];          // "Asma"
const key = "name";
user[key];             // "Asma"

// Optional chaining — safe access, returns undefined instead of throwing
user?.address?.city;   // "Oslo"
user?.phone?.number;   // undefined (no error)
user?.greet?.();       // undefined (no error if greet doesn't exist)

// Nullish coalescing with optional chaining
const city = user?.address?.city ?? "Unknown";

Modifying Objects

JavaScript
const user = { name: "Asma", age: 25 };

// Add/update property
user.email = "asma@example.com";
user.age = 26;

// Delete property
delete user.age;

// Check if property exists
"name" in user;         // true
"age" in user;          // false
user.hasOwnProperty("name"); // true

Object Methods

JavaScript
const obj = { a: 1, b: 2, c: 3 };

Object.keys(obj);    // ["a", "b", "c"]
Object.values(obj);  // [1, 2, 3]
Object.entries(obj); // [["a",1], ["b",2], ["c",3]]

// From entries (reverse of entries)
Object.fromEntries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }

// Useful: transform object values
const doubled = Object.fromEntries(
  Object.entries(obj).map(([k, v]) => [k, v * 2])
);
// { a: 2, b: 4, c: 6 }

Object Spread and Destructuring

JavaScript
// Spread — shallow copy or merge
const defaults = { theme: "light", lang: "en", notifications: true };
const userPrefs = { lang: "no", theme: "dark" };
const merged = { ...defaults, ...userPrefs };
// { theme: "dark", lang: "no", notifications: true }
// Later properties override earlier ones

// Immutable update pattern (common in React)
const user = { id: 1, name: "Asma", role: "user" };
const updated = { ...user, role: "admin" };
// Original user unchanged

// Destructuring
const { name, email, role = "user" } = user;
name;  // "Asma"
email; // undefined (doesn't exist)
role;  // "user" (default)

// Rename while destructuring
const { name: userName } = user;
userName; // "Asma"

// Nested destructuring
const { address: { city, country } } = { address: { city: "Oslo", country: "Norway" }};
city;    // "Oslo"
country; // "Norway"

// Rest in object destructuring
const { id, ...rest } = user;
id;   // 1
rest; // { name: "Asma", role: "user" }

Array.from and Useful Conversions

JavaScript
// Array.from — create array from iterable or array-like
Array.from("hello");           // ["h","e","l","l","o"]
Array.from({ length: 5 }, (_, i) => i); // [0,1,2,3,4]
Array.from(new Set([1,1,2,2,3]));        // [1,2,3] — deduplicate

// Convert object to array for iteration
const scores = { Alice: 95, Bob: 87, Carol: 92 };
const sorted = Object.entries(scores)
  .sort(([,a], [,b]) => b - a)
  .map(([name, score]) => `${name}: ${score}`);
// ["Alice: 95", "Carol: 92", "Bob: 87"]

Practical Example: Product Catalogue

JavaScript
const products = [
  { id: 1, name: "Laptop",   category: "Electronics", price: 999, stock: 5 },
  { id: 2, name: "Desk",     category: "Furniture",   price: 249, stock: 0 },
  { id: 3, name: "Monitor",  category: "Electronics", price: 349, stock: 12 },
  { id: 4, name: "Chair",    category: "Furniture",   price: 199, stock: 3 },
  { id: 5, name: "Keyboard", category: "Electronics", price: 79,  stock: 20 },
];

// Available electronics under $400, sorted by price
const results = products
  .filter(p => p.stock > 0 && p.category === "Electronics" && p.price < 400)
  .sort((a, b) => a.price - b.price)
  .map(({ name, price, stock }) => ({ name, price, stock }));

// Group by category
const byCategory = products.reduce((acc, p) => {
  (acc[p.category] ??= []).push(p);
  return acc;
}, {});

// Total value in stock
const totalValue = products.reduce((sum, p) => sum + (p.price * p.stock), 0);

Key Takeaways

  1. map, filter, reduce are your core tools — master these
  2. Spread (...) creates shallow copies — nested objects are still shared
  3. Destructuring makes extraction clean and readable
  4. Optional chaining (?.) prevents "cannot read property of undefined" errors
  5. Object.entries() + array methods = full power to transform objects
  6. Chain array methods to express data pipelines clearly