Skip to main content

Iterable Types

Data Types: Iterable Types



What are iterables in JavaScript?

View Answer:
Interview Response: Iterables in JavaScript are objects that can be iterated upon using the "for...of" loop. They include arrays, strings, maps, sets, and other custom objects with a Symbol.iterator property.

Technical Response: Iterable objects are a subset of arrays. This notion allows us to use any object in a for...of loop. Arrays, of course, are iterable. However, several additional built-in objects are iterable as well. Strings, for example, are also iterable. It is a data structure that allows consumption of its data in general. It does this by implementing a method with the key Symbol.iterator, which returns an iterator. The iterator interface provides another method called return(), which gets performed when the iteration reaches the last value or is deliberately halted by calling it directly or using break; a for loop.

Code Example:

Here's an example of using an iterable (an array) in JavaScript:

// Arrays contain Symbol.iterator property
const myArray = [1, 2, 3, 4, 5];

for (const item of myArray) {
console.log(item);
}

In this code, the myArray variable is an iterable (an array) containing numbers. The for...of loop iterates over each item in the array and logs it to the console. Output:

1
2
3
4
5

What is the purpose of the Symbol.iterator method?

View Answer:
Interview Response: The purpose of the Symbol.iterator method is to define the default iterator for an object. It allows the object to be iterable, enabling it to be used with iteration protocols like the for...of loop.

Code Example:

Here's an example of implementing the Symbol.iterator method to create a custom iterable object in JavaScript.

const myIterable = {
data: [1, 2, 3, 4, 5],
[Symbol.iterator]() {
let index = 0;
const data = this.data;
return {
next() {
if (index < data.length) {
return { value: data[index++], done: false };
} else {
return { done: true };
}
}
};
}
};

for (const item of myIterable) {
console.log(item);
}

In this code, myIterable is an object that implements the Symbol.iterator method. The method returns an iterator object with a next() function, which is responsible for generating the values in the iteration. The for...of loop iterates over the iterable object and logs each item to the console. Output:

1
2
3
4
5

Note that the Symbol.iterator method allows custom objects to be iterable, providing control over how they can be iterated.


What can we use the Symbol.iterator for in JavaScript?

View Answer:
Interview Response: The Symbol.iterator is used to define a custom iteration behavior for objects, making them iterable and compatible with the for...of loop.

Code Example:

let range = {
from: 1,
to: 5,
};

// 1. call to for..of initially calls this
range[Symbol.iterator] = function () {
// ...it returns the iterator object:
// 2. Onward, for..of works only with this iterator, asking it for next values
return {
current: this.from,
last: this.to,

// 3. next() is called on each iteration by the for..of loop
next() {
// 4. it should return the value as an object {done:.., value :...}
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
},
};
};

// now it works!
for (let num of range) {
console.log(num); // 1, then 2, 3, 4, 5
}

Can you call an iterator explicitly, and what are the benefits?

View Answer:
Interview Response: Yes, you can call an iterator explicitly using the iterator's next() method. Benefits include precise control over iteration, customized iteration behavior, and on-demand value generation.

Code Example:

let str = 'Hello';

// does the same as
// for (let char of str) console.log(char);

let iterator = str[Symbol.iterator]();

while (true) {
let result = iterator.next();
if (result.done) break;
console.log(result.value); // outputs characters one by one
}

What is the difference between an iterable and an array-like object?

View Answer:
Interview Response: An iterable is an object with a [Symbol.iterator] method that returns an iterator, while an array-like object has numeric keys and a length property. Iterables can be iterated over with for-of loops, while array-like objects cannot.

Code Example: Array-like but not Iterable

let arrayLike = {
// has indexes and length => array-like
0: 'Hello',
1: 'World',
length: 2,
};

// Error (no Symbol.iterator)
// TypeError: arrayLike is not **iterable**
for (let item of arrayLike) {
console.log(item)
}

What universal method can we use to turn an iterable or array-like value into an array?

View Answer:
Interview Response: In JavaScript, by using the Array.from() method, we can convert an iterable or an array-like value into an array, which allows us to call array methods on it or looping mechanisms.

Syntax Example: Array.from(arrayLike, (element, index) => )

Array.from(obj[, mapFn, thisArg]);

Code Example:

let arrayLike = {
0: 'Hello',
1: 'World',
length: 2,
};

let arr = Array.from(arrayLike); // (*)
console.log(arr.pop()); // World (method works)

for(let item of arr) {
console.log(item); // logs "Hello"
}

// Here we use Array.from to turn a string into an array of characters:

let str = '𝒳😂';

// splits str into array of characters
let chars = Array.from(str);

console.log(chars[0]); // 𝒳
console.log(chars[1]); // 😂
console.log(chars.length); // 2

How can we create our own iterable object?

View Answer:
Interview Response: To create an iterable object in JavaScript, define a custom iterator function within the object, implementing the Symbol.iterator method, which returns an iterator with next() method to control iteration.

Code Example:

const myIterableObject = {
data: [1, 2, 3, 4, 5],
[Symbol.iterator]() {
let index = 0;
const data = this.data;

return {
next() {
if (index < data.length) {
return { value: data[index++], done: false };
} else {
return { done: true };
}
}
};
}
};

for (const item of myIterableObject) {
console.log(item);
}


How does lazy evaluation work with iterable objects?

View Answer:
Interview Response: Lazy evaluation involves delaying the evaluation of data until it is actually needed. With iterable objects, this means that data is only loaded into memory as it is iterated over, which can reduce memory usage and improve performance.

Code Example:

const lazyIterableObject = {
data: [1, 2, 3, 4, 5],
[Symbol.iterator]() {
let index = 0;
const data = this.data;

return {
next() {
if (index < data.length) {
// Perform some lazy computation
const computedValue = data[index] * 2;
index++;

return { value: computedValue, done: false };
} else {
return { done: true };
}
}
};
}
};

for (const item of lazyIterableObject) {
console.log(item);
}


What is the difference between forEach() and for...of when iterating over arrays?

View Answer:
Interview Response: The forEach() is a method that iterates over array elements and executes a callback function on each element. for...of is a language construct that provides a concise syntax for iterating over iterable objects, including arrays, to access each element directly.

Interview Response: forEach() is a method on the array prototype that calls a provided function for each element in the array. for...of is a language feature for iterating over any iterable object, including arrays, yielding the values one-by-one. The primary difference is that forEach() provides no way to break out of the loop or to skip to the next iteration, while for...of allows for the use of the break and continue statements.

Code Example:

const myArray = [1, 2, 3, 4, 5];

// Using forEach()
myArray.forEach((element) => {
console.log(element);
});

// Using for...of
for (const element of myArray) {
console.log(element);
}