Iterables and Generators
Custom Iterable Objects
An object can work with for...of when it provides an iterator.
custom iterable
A custom iterable implements `Symbol.iterator` and returns an iterator with a `next` method.
Custom Iterable Objects
custom.ts
Replay: real traced execution (multi-file project)
class NumberRange implements Iterable<number> {
start: number;
end: number;
constructor(start: number, end: number) {
this.start = start;
this.end = end;
}
[Symbol.iterator](): Iterator<number> {
let current: number = this.start;
const last: number = this.end;
return {
next(): IteratorResult<number> {
if (current <= last) {
const value: number = current;
current = current + 1;
return { value: value, done: false };
}
return { value: 0, done: true };
},
};
}
}
const endValue: number = 3;
const range: NumberRange = new NumberRange(1, endValue);
const visited: number[] = [];
for (const value of range) {
visited.push(value);
}
console.log(visited.join("-"));
class NumberRange implements Iterable<number> {
start: number;
end: number;
constructor(start: number, end: number) {
this.start = start;
this.end = end;
}
[Symbol.iterator](): Iterator<number> {
let current: number = this.start;
const last: number = this.end;
return {
next(): IteratorResult<number> {
if (current <= last) {
const value: number = current;
current = current + 1;
return { value: value, done: false };
}
return { value: 0, done: true };
},
};
}
}
const endValue: number = 2;
const range: NumberRange = new NumberRange(1, endValue);
const visited: number[] = [];
for (const value of range) {
visited.push(value);
}
console.log(visited.join("-"));
class NumberRange implements Iterable<number> {
start: number;
end: number;
constructor(start: number, end: number) {
this.start = start;
this.end = end;
}
[Symbol.iterator](): Iterator<number> {
let current: number = this.start;
const last: number = this.end;
return {
next(): IteratorResult<number> {
if (current <= last) {
const value: number = current;
current = current + 1;
return { value: value, done: false };
}
return { value: 0, done: true };
},
};
}
}
const endValue: number = 4;
const range: NumberRange = new NumberRange(1, endValue);
const visited: number[] = [];
for (const value of range) {
visited.push(value);
}
console.log(visited.join("-"));
endValue ← 3, this.start ← 1, this.end ← 3, range ← [object Object]
5 constructor(start: number, end: number) {6 this.start = start1;7 this.end = end3;8 }910 [Symbol.iterator](): Iterator<number> {11 let current: number = this.start;12 const last: number = this.end;13 return {14 next(): IteratorResult<number> {15 if (current <= last) {16 const value: number = current;17 current = current + 1;18 return { value: value, done: false };19 }20 return { value: 0, done: true };21 },22 };23 }24}2526const endValue→ 3: number = 3; //@endValue=2, 427const range→ [object Object]: NumberRange = new NumberRange(1, endValue3);28const visited→ (empty): number[] = [];values this step1this.start3this.endcurrent ← 1, this.start ← 1, last ← 3, this.end ← 3
7 this.end = end;8}910[Symbol.iterator](): Iterator<number> {11 let current→ 1: number = this.start→ 1;12 const last→ 3: number = this.end→ 3;13 return {14 next(): IteratorResult<number> {15 if (current <= last) {16 const value: number = current;17 current = current + 1;18 return { value: value, done: false };19 }20 return { value: 0, done: true };21 },22 };23}visited ← 1,2,3
30for (const value of range) {31 visited.push(value3);32}3334console.log(visited1,2,3.join("-"));output1-2-3
endValue ← 2, this.start ← 1, this.end ← 2, range ← [object Object]
5 constructor(start: number, end: number) {6 this.start = start1;7 this.end = end2;8 }910 [Symbol.iterator](): Iterator<number> {11 let current: number = this.start;12 const last: number = this.end;13 return {14 next(): IteratorResult<number> {15 if (current <= last) {16 const value: number = current;17 current = current + 1;18 return { value: value, done: false };19 }20 return { value: 0, done: true };21 },22 };23 }24}2526const endValue→ 2: number = 2;27const range→ [object Object]: NumberRange = new NumberRange(1, endValue2);28const visited→ (empty): number[] = [];values this step1this.start2this.endcurrent ← 1, this.start ← 1, last ← 2, this.end ← 2
7 this.end = end;8}910[Symbol.iterator](): Iterator<number> {11 let current→ 1: number = this.start→ 1;12 const last→ 2: number = this.end→ 2;13 return {14 next(): IteratorResult<number> {15 if (current <= last) {16 const value: number = current;17 current = current + 1;18 return { value: value, done: false };19 }20 return { value: 0, done: true };21 },22 };23}visited ← 1,2
30for (const value of range) {31 visited.push(value2);32}3334console.log(visited1,2.join("-"));output1-2
endValue ← 4, this.start ← 1, this.end ← 4, range ← [object Object]
5 constructor(start: number, end: number) {6 this.start = start1;7 this.end = end4;8 }910 [Symbol.iterator](): Iterator<number> {11 let current: number = this.start;12 const last: number = this.end;13 return {14 next(): IteratorResult<number> {15 if (current <= last) {16 const value: number = current;17 current = current + 1;18 return { value: value, done: false };19 }20 return { value: 0, done: true };21 },22 };23 }24}2526const endValue→ 4: number = 4;27const range→ [object Object]: NumberRange = new NumberRange(1, endValue4);28const visited→ (empty): number[] = [];values this step1this.start4this.endcurrent ← 1, this.start ← 1, last ← 4, this.end ← 4
7 this.end = end;8}910[Symbol.iterator](): Iterator<number> {11 let current→ 1: number = this.start→ 1;12 const last→ 4: number = this.end→ 4;13 return {14 next(): IteratorResult<number> {15 if (current <= last) {16 const value: number = current;17 current = current + 1;18 return { value: value, done: false };19 }20 return { value: 0, done: true };21 },22 };23}visited ← 1,2,3,4
30for (const value of range) {31 visited.push(value4);32}3334console.log(visited1,2,3,4.join("-"));output1-2-3-4