Arrays & Objects

Arrays and Objects Together

Arrays and objects are the most commonly used data structures in JavaScript. Understanding how to manipulate and transform them is essential.

Try Arrays & Objects

Code Editor
Console Output
Click "Run" to execute your code...

Example 1: Creating and Accessing

// Creating arrays
const arr1 = [1, 2, 3];
const arr2 = new Array(1, 2, 3);
const arr3 = Array.of(1, 2, 3);
const arr4 = Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']

// Creating objects
const obj1 = { name: 'John', age: 30 };
const obj2 = new Object();
obj2.name = 'Jane';
const obj3 = Object.create(null); // No prototype

// Accessing array elements
console.log(arr1[0]); // 1
console.log(arr1.at(-1)); // 3 (last element)

// Accessing object properties
console.log(obj1.name); // John
console.log(obj1['age']); // 30

// Dynamic property access
const key = 'name';
console.log(obj1[key]); // John

// Nested structures
const data = {
  user: {
    name: 'John',
    contacts: ['email', 'phone'],
    address: {
      city: 'New York',
      zip: '10001'
    }
  }
};

console.log(data.user.name); // John
console.log(data.user.contacts[0]); // email
console.log(data.user.address.city); // New York

// Optional chaining
console.log(data.user?.contacts?.[0]); // email
console.log(data.user?.social?.twitter); // undefined (no error)

// Array of objects
const users = [
  { id: 1, name: 'John', age: 30 },
  { id: 2, name: 'Jane', age: 25 },
  { id: 3, name: 'Bob', age: 35 }
];

console.log(users[0].name); // John
console.log(users.find(u => u.id === 2).name); // Jane

Example 2: Destructuring and Spreading

// Array destructuring
const numbers = [1, 2, 3, 4, 5];
const [first, second, ...rest] = numbers;
console.log(first);  // 1
console.log(second); // 2
console.log(rest);   // [3, 4, 5]

// Skip elements
const [a, , c] = numbers;
console.log(a, c); // 1 3

// Object destructuring
const user = { name: 'John', age: 30, city: 'NYC' };
const { name, age } = user;
console.log(name, age); // John 30

// Rename variables
const { name: userName, age: userAge } = user;
console.log(userName, userAge); // John 30

// Default values
const { name, country = 'USA' } = user;
console.log(country); // USA

// Nested destructuring
const person = {
  name: 'John',
  address: {
    city: 'New York',
    zip: '10001'
  }
};

const { address: { city, zip } } = person;
console.log(city, zip); // New York 10001

// Array spread
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]

// Object spread
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 2, c: 3, d: 4 }

// Spread with overrides
const defaults = { theme: 'light', lang: 'en' };
const userPrefs = { theme: 'dark' };
const settings = { ...defaults, ...userPrefs };
console.log(settings); // { theme: 'dark', lang: 'en' }

// Rest in function parameters
function sum(...numbers) {
  return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10

// Object destructuring in parameters
function greet({ name, age }) {
  console.log(`Hello ${name}, you are ${age}`);
}
greet({ name: 'John', age: 30 }); // Hello John, you are 30

Example 3: Transforming Data

// Array to Object
const fruits = ['apple', 'banana', 'orange'];
const fruitObj = fruits.reduce((acc, fruit, index) => {
  acc[index] = fruit;
  return acc;
}, {});
console.log(fruitObj); // { 0: 'apple', 1: 'banana', 2: 'orange' }

// Object to Array
const person = { name: 'John', age: 30, city: 'NYC' };
const entries = Object.entries(person);
console.log(entries); // [['name', 'John'], ['age', 30], ['city', 'NYC']]

const keys = Object.keys(person);
console.log(keys); // ['name', 'age', 'city']

const values = Object.values(person);
console.log(values); // ['John', 30, 'NYC']

// Array of objects to object
const users = [
  { id: 1, name: 'John' },
  { id: 2, name: 'Jane' },
  { id: 3, name: 'Bob' }
];

const usersById = users.reduce((acc, user) => {
  acc[user.id] = user;
  return acc;
}, {});
console.log(usersById);
// { 1: { id: 1, name: 'John' }, 2: { id: 2, name: 'Jane' }, ... }

// Group by property
const people = [
  { name: 'John', age: 30 },
  { name: 'Jane', age: 25 },
  { name: 'Bob', age: 30 }
];

const byAge = people.reduce((acc, person) => {
  if (!acc[person.age]) {
    acc[person.age] = [];
  }
  acc[person.age].push(person);
  return acc;
}, {});
console.log(byAge);
// { 25: [{...}], 30: [{...}, {...}] }

// Extract specific properties
const simplified = users.map(({ id, name }) => ({ id, name }));
console.log(simplified);

// Merge arrays of objects
const arr1 = [{ id: 1, name: 'John' }];
const arr2 = [{ id: 2, name: 'Jane' }];
const merged = [...arr1, ...arr2];

// Deep merge
function deepMerge(obj1, obj2) {
  const result = { ...obj1 };
  
  for (const key in obj2) {
    if (obj2[key] instanceof Object && !Array.isArray(obj2[key])) {
      result[key] = deepMerge(result[key] || {}, obj2[key]);
    } else {
      result[key] = obj2[key];
    }
  }
  
  return result;
}

const a = { x: 1, y: { z: 2 } };
const b = { y: { w: 3 }, z: 4 };
console.log(deepMerge(a, b)); // { x: 1, y: { z: 2, w: 3 }, z: 4 }

Example 4: Cloning and Copying

// Shallow copy - arrays
const original = [1, 2, 3];
const copy1 = [...original];
const copy2 = original.slice();
const copy3 = Array.from(original);

copy1.push(4);
console.log(original); // [1, 2, 3] (unchanged)
console.log(copy1);    // [1, 2, 3, 4]

// Problem with nested arrays
const nested = [[1, 2], [3, 4]];
const shallowCopy = [...nested];
shallowCopy[0].push(3);
console.log(nested);      // [[1, 2, 3], [3, 4]] (changed!)
console.log(shallowCopy); // [[1, 2, 3], [3, 4]]

// Deep copy - arrays
const deepCopy = JSON.parse(JSON.stringify(nested));
deepCopy[0].push(999);
console.log(nested);   // [[1, 2, 3], [3, 4]] (unchanged)
console.log(deepCopy); // [[1, 2, 3, 999], [3, 4]]

// Shallow copy - objects
const obj = { a: 1, b: 2 };
const copy4 = { ...obj };
const copy5 = Object.assign({}, obj);

copy4.a = 999;
console.log(obj);   // { a: 1, b: 2 } (unchanged)
console.log(copy4); // { a: 999, b: 2 }

// Problem with nested objects
const nestedObj = {
  user: { name: 'John', age: 30 },
  settings: { theme: 'dark' }
};

const shallowObjCopy = { ...nestedObj };
shallowObjCopy.user.name = 'Jane';
console.log(nestedObj.user.name);      // Jane (changed!)
console.log(shallowObjCopy.user.name); // Jane

// Deep copy - objects
const deepObjCopy = JSON.parse(JSON.stringify(nestedObj));
deepObjCopy.user.name = 'Bob';
console.log(nestedObj.user.name);   // Jane (unchanged)
console.log(deepObjCopy.user.name); // Bob

// Custom deep clone
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  
  if (Array.isArray(obj)) {
    return obj.map(item => deepClone(item));
  }
  
  const cloned = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloned[key] = deepClone(obj[key]);
    }
  }
  
  return cloned;
}

// Modern alternative: structuredClone (ES2022)
// const deepClone = structuredClone(nestedObj);

Example 5: Common Patterns

// 1. Filter and map combo
const products = [
  { name: 'Laptop', price: 1000, inStock: true },
  { name: 'Phone', price: 500, inStock: false },
  { name: 'Tablet', price: 300, inStock: true }
];

const availableNames = products
  .filter(p => p.inStock)
  .map(p => p.name);
console.log(availableNames); // ['Laptop', 'Tablet']

// 2. Find and update
const updateUser = (users, id, updates) => {
  return users.map(user => 
    user.id === id ? { ...user, ...updates } : user
  );
};

// 3. Remove duplicates
const numbers = [1, 2, 2, 3, 4, 4, 5];
const unique = [...new Set(numbers)];
console.log(unique); // [1, 2, 3, 4, 5]

const users = [
  { id: 1, name: 'John' },
  { id: 2, name: 'Jane' },
  { id: 1, name: 'John' }
];

const uniqueUsers = Array.from(
  new Map(users.map(u => [u.id, u])).values()
);
console.log(uniqueUsers); // Only unique by id

// 4. Sorting arrays of objects
const people = [
  { name: 'John', age: 30 },
  { name: 'Jane', age: 25 },
  { name: 'Bob', age: 35 }
];

// Sort by age
people.sort((a, b) => a.age - b.age);

// Sort by name
people.sort((a, b) => a.name.localeCompare(b.name));

// 5. Flattening nested arrays
const nestedArr = [[1, 2], [3, [4, 5]], 6];
const flat1 = nestedArr.flat(); // [1, 2, 3, [4, 5], 6]
const flat2 = nestedArr.flat(2); // [1, 2, 3, 4, 5, 6]
const flatAll = nestedArr.flat(Infinity); // Fully flat

// 6. Chunking array
function chunk(arr, size) {
  return Array.from(
    { length: Math.ceil(arr.length / size) },
    (_, i) => arr.slice(i * size, i * size + size)
  );
}

console.log(chunk([1, 2, 3, 4, 5], 2)); // [[1, 2], [3, 4], [5]]

// 7. Object pick/omit
function pick(obj, keys) {
  return keys.reduce((acc, key) => {
    if (key in obj) acc[key] = obj[key];
    return acc;
  }, {});
}

function omit(obj, keys) {
  return Object.keys(obj)
    .filter(key => !keys.includes(key))
    .reduce((acc, key) => {
      acc[key] = obj[key];
      return acc;
    }, {});
}

const user = { name: 'John', age: 30, city: 'NYC', country: 'USA' };
console.log(pick(user, ['name', 'age'])); // { name: 'John', age: 30 }
console.log(omit(user, ['city', 'country'])); // { name: 'John', age: 30 }

Key Points

  • Use destructuring to extract values from arrays and objects
  • Spread operator creates shallow copies
  • Use map/filter/reduce for array transformations
  • Object.keys/values/entries convert objects to arrays
  • Shallow copies don't clone nested structures
  • JSON.parse(JSON.stringify()) for simple deep cloning
  • Combine methods for powerful data transformations