HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
4 Topics
Chapter•65 Minutes

Arrays, Collections, Iterables, and Iterators

Learn how arrays actually behave, when to use Map and Set, how iteration protocols work, and how generators provide lazy iteration.

Arrays Are Objects with Special Behavior

JavaScript arrays are objects with indexed properties and a special length property. They can contain values of different types and can be sparse. Array methods such as push, pop, slice, and splice differ in whether they mutate the original array.

Understanding mutation matters when working with React state, functional programming, caching, and shared data structures.

slice vs splice
const values = [1, 2, 3, 4];

const copy = values.slice(1, 3);
console.log(copy);
console.log(values);

values.splice(1, 2);
console.log(values);
💡 slice creates a new array without changing the source. splice removes or replaces elements in the original array.
Key Takeaways
  • Arrays are objects with special indexed and length behavior.
  • slice does not mutate the source array.
  • splice mutates the original array.
Knowledge Check

Which method mutates an array by removing or replacing elements?

Map and Set

Map stores key-value pairs and allows keys of any value type. Unlike ordinary objects, a Map does not convert keys to strings. Set stores unique values and is useful for membership checks and deduplication.

Maps and Sets are often preferable to objects and arrays when their semantics match the problem.

Map and Set
const users = new Map();
users.set(101, { name: 'Suriya' });

const ids = new Set([1, 1, 2, 3, 3]);

console.log(users.get(101));
console.log([...ids]);
💡 Map preserves the numeric key 101 as a numeric key. Set automatically keeps only unique values.
Key Takeaways
  • Map supports arbitrary key types.
  • Set stores unique values.
  • Use collection types according to the semantics you need.
Knowledge Check

What is a key advantage of Map over a plain object?

The Iterable Protocol

An object is iterable when it provides a method at Symbol.iterator that returns an iterator. The iterator provides a next() method returning objects shaped like { value, done }.

The for...of loop, spread syntax, array destructuring, and many collection APIs consume iterables. This is why custom objects can participate in standard iteration without being arrays.

Custom Iterable
const range = {
  start: 1,
  end: 3,
  *[Symbol.iterator]() {
    for (let value = this.start; value <= this.end; value++) {
      yield value;
    }
  }
};

console.log([...range]);
💡 The object defines Symbol.iterator using a generator, making it compatible with the iterable protocol.
Key Takeaways
  • Iterable objects expose Symbol.iterator.
  • Iterators expose next().
  • for...of consumes iterables rather than requiring arrays specifically.
Knowledge Check

Which symbol is used to define an object's default iteration behavior?

Generators and Lazy Evaluation

A generator function is declared using function* and can pause execution with yield. Calling a generator function returns a generator object rather than immediately executing the entire body.

Generators are useful for lazy sequences, custom iteration, and controlling incremental computation. They can also receive values through subsequent next(value) calls.

A Generator Sequence
function* ids() {
  let id = 1;
  while (true) {
    yield id++;
  }
}

const iterator = ids();
console.log(iterator.next().value);
console.log(iterator.next().value);
💡 The generator pauses at each yield. Each call to next resumes it until another yield or completion.
Key Takeaways
  • Generators pause and resume execution.
  • Generator functions return iterator-like generator objects.
  • Generators enable lazy computation.
Knowledge Check

What does calling a generator function return?