Skip to content

Commit 5a87dd2

Browse files
committed
iterable
1 parent 625a1c0 commit 5a87dd2

File tree

1 file changed

+27
-32
lines changed

1 file changed

+27
-32
lines changed

1-js/05-data-types/06-iterable/article.md

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1+
# Iteriebare
12

2-
# Iterables
3-
4-
*Iterable* objects is a generalization of arrays. That's a concept that allows us to make any object useable in a `for..of` loop.
3+
_Iteriebare_ Objekte sind eine Verallgemeinerung von Arrays. Das Konzept ermöglicht es uns, jedes Objekt in einer `for..of` -Schleife zu verwenden.
54

65
Of course, Arrays are iterable. But there are many other built-in objects, that are iterable as well. For instance, strings are also iterable.
76

87
If an object isn't technically an array, but represents a collection (list, set) of something, then `for..of` is a great syntax to loop over it, so let's see how to make it work.
98

10-
119
## Symbol.iterator
1210

1311
We can easily grasp the concept of iterables by making one of our own.
@@ -19,7 +17,7 @@ Like a `range` object that represents an interval of numbers:
1917
```js
2018
let range = {
2119
from: 1,
22-
to: 5
20+
to: 5,
2321
};
2422

2523
// We want the for..of to work:
@@ -28,27 +26,26 @@ let range = {
2826

2927
To make the `range` iterable (and thus let `for..of` work) we need to add a method to the object named `Symbol.iterator` (a special built-in symbol just for that).
3028

31-
1. When `for..of` starts, it calls that method once (or errors if not found). The method must return an *iterator* -- an object with the method `next`.
32-
2. Onward, `for..of` works *only with that returned object*.
29+
1. When `for..of` starts, it calls that method once (or errors if not found). The method must return an _iterator_ -- an object with the method `next`.
30+
2. Onward, `for..of` works _only with that returned object_.
3331
3. When `for..of` wants the next value, it calls `next()` on that object.
34-
4. The result of `next()` must have the form `{done: Boolean, value: any}`, where `done=true` means that the iteration is finished, otherwise `value` is the next value.
32+
4. The result of `next()` must have the form `{done: Boolean, value: any}`, where `done=true` means that the iteration is finished, otherwise `value` is the next value.
3533

3634
Here's the full implementation for `range` with remarks:
3735

3836
```js run
3937
let range = {
4038
from: 1,
41-
to: 5
39+
to: 5,
4240
};
4341

4442
// 1. call to for..of initially calls this
45-
range[Symbol.iterator] = function() {
46-
43+
range[Symbol.iterator] = function () {
4744
// ...it returns the iterator object:
4845
// 2. Onward, for..of works only with this iterator, asking it for next values
4946
return {
5047
current: this.from,
51-
last: this.to,
48+
last: this.to,
5249

5350
// 3. next() is called on each iteration by the for..of loop
5451
next() {
@@ -58,7 +55,7 @@ range[Symbol.iterator] = function() {
5855
} else {
5956
return { done: true };
6057
}
61-
}
58+
},
6259
};
6360
};
6461

@@ -95,15 +92,15 @@ let range = {
9592
} else {
9693
return { done: true };
9794
}
98-
}
95+
},
9996
};
10097

10198
for (let num of range) {
10299
alert(num); // 1, then 2, 3, 4, 5
103100
}
104101
```
105102

106-
Now `range[Symbol.iterator]()` returns the `range` object itself: it has the necessary `next()` method and remembers the current iteration progress in `this.current`. Shorter? Yes. And sometimes that's fine too.
103+
Now `range[Symbol.iterator]()` returns the `range` object itself: it has the necessary `next()` method and remembers the current iteration progress in `this.current`. Shorter? Yes. And sometimes that's fine too.
107104

108105
The downside is that now it's impossible to have two `for..of` loops running over the object simultaneously: they'll share the iteration state, because there's only one iterator -- the object itself. But two parallel for-ofs is a rare thing, even in async scenarios.
109106

@@ -115,17 +112,16 @@ There are no limitations on `next`, it can return more and more values, that's n
115112
Of course, the `for..of` loop over such an iterable would be endless. But we can always stop it using `break`.
116113
```
117114

118-
119115
## String is iterable
120116

121117
Arrays and strings are most widely used built-in iterables.
122118

123119
For a string, `for..of` loops over its characters:
124120

125121
```js run
126-
for (let char of "test") {
122+
for (let char of 'test') {
127123
// triggers 4 times: once for each character
128-
alert( char ); // t, then e, then s, then t
124+
alert(char); // t, then e, then s, then t
129125
}
130126
```
131127

@@ -134,7 +130,7 @@ And it works correctly with surrogate pairs!
134130
```js run
135131
let str = '𝒳😂';
136132
for (let char of str) {
137-
alert( char ); // 𝒳, and then 😂
133+
alert(char); // 𝒳, and then 😂
138134
}
139135
```
140136

@@ -167,8 +163,8 @@ That is rarely needed, but gives us more control over the process than `for..of`
167163

168164
There are two official terms that look similar, but are very different. Please make sure you understand them well to avoid the confusion.
169165

170-
- *Iterables* are objects that implement the `Symbol.iterator` method, as described above.
171-
- *Array-likes* are objects that have indexes and `length`, so they look like arrays.
166+
- _Iterables_ are objects that implement the `Symbol.iterator` method, as described above.
167+
- _Array-likes_ are objects that have indexes and `length`, so they look like arrays.
172168

173169
When we use JavaScript for practical tasks in browser or other environments, we may meet objects that are iterables or array-likes, or both.
174170

@@ -193,7 +189,7 @@ for (let item of arrayLike) {}
193189
*/!*
194190
```
195191

196-
Both iterables and array-likes are usually *not arrays*, they don't have `push`, `pop` etc. That's rather inconvenient if we have such an object and want to work with it as with an array. E.g. we would like to work with `range` using array methods. How to achieve that?
192+
Both iterables and array-likes are usually _not arrays_, they don't have `push`, `pop` etc. That's rather inconvenient if we have such an object and want to work with it as with an array. E.g. we would like to work with `range` using array methods. How to achieve that?
197193

198194
## Array.from
199195

@@ -225,6 +221,7 @@ alert(arr); // 1,2,3,4,5 (array toString conversion works)
225221
```
226222

227223
The full syntax for `Array.from` also allows us to provide an optional "mapping" function:
224+
228225
```js
229226
Array.from(obj[, mapFn, thisArg])
230227
```
@@ -237,7 +234,7 @@ For instance:
237234
// assuming that range is taken from the example above
238235

239236
// square each number
240-
let arr = Array.from(range, num => num * num);
237+
let arr = Array.from(range, (num) => num * num);
241238

242239
alert(arr); // 1,4,9,16,25
243240
```
@@ -270,7 +267,7 @@ for (let char of str) {
270267
alert(chars);
271268
```
272269

273-
...But it is shorter.
270+
...But it is shorter.
274271

275272
We can even build surrogate-aware `slice` on it:
276273

@@ -281,26 +278,24 @@ function slice(str, start, end) {
281278

282279
let str = '𝒳😂𩷶';
283280

284-
alert( slice(str, 1, 3) ); // 😂𩷶
281+
alert(slice(str, 1, 3)); // 😂𩷶
285282

286283
// the native method does not support surrogate pairs
287-
alert( str.slice(1, 3) ); // garbage (two pieces from different surrogate pairs)
284+
alert(str.slice(1, 3)); // garbage (two pieces from different surrogate pairs)
288285
```
289286

290-
291287
## Summary
292288

293-
Objects that can be used in `for..of` are called *iterable*.
289+
Objects that can be used in `for..of` are called _iterable_.
294290

295291
- Technically, iterables must implement the method named `Symbol.iterator`.
296-
- The result of `obj[Symbol.iterator]` is called an *iterator*. It handles the further iteration process.
297-
- An iterator must have the method named `next()` that returns an object `{done: Boolean, value: any}`, here `done:true` denotes the end of the iteration process, otherwise the `value` is the next value.
292+
- The result of `obj[Symbol.iterator]` is called an _iterator_. It handles the further iteration process.
293+
- An iterator must have the method named `next()` that returns an object `{done: Boolean, value: any}`, here `done:true` denotes the end of the iteration process, otherwise the `value` is the next value.
298294
- The `Symbol.iterator` method is called automatically by `for..of`, but we also can do it directly.
299295
- Built-in iterables like strings or arrays, also implement `Symbol.iterator`.
300296
- String iterator knows about surrogate pairs.
301297

302-
303-
Objects that have indexed properties and `length` are called *array-like*. Such objects may also have other properties and methods, but lack the built-in methods of arrays.
298+
Objects that have indexed properties and `length` are called _array-like_. Such objects may also have other properties and methods, but lack the built-in methods of arrays.
304299

305300
If we look inside the specification -- we'll see that most built-in methods assume that they work with iterables or array-likes instead of "real" arrays, because that's more abstract.
306301

0 commit comments

Comments
 (0)