You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/05-data-types/06-iterable/article.md
+17-16Lines changed: 17 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@
5
5
6
6
Arrays by themselves are iterable. But not only arrays. Strings are iterable too, and many other built-in objects as well.
7
7
8
-
Iterables are widely used by the core JavaScript, as we'll see many operators and built-in methods rely on them.
8
+
Iterables are widely used by the core JavaScript. As we'll see many built-in operators and methods rely on them.
9
9
10
10
[cut]
11
11
@@ -23,13 +23,13 @@ let range = {
23
23
to:5
24
24
};
25
25
26
-
// We want for..of to work:
26
+
// We want the for..of to work:
27
27
// for(let num of range) ... num=1,2,3,4,5
28
28
```
29
29
30
30
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).
31
31
32
-
- When `for..of` starts, it calls that method (or errors if none found).
32
+
- When `for..of` starts, it calls that method (or errors if not found).
33
33
- The method must return an *iterator* -- an object with the method `next`.
34
34
- When `for..of` wants the next value, it calls `next()` on that object.
35
35
- The result of `next()` must have the form `{done: Boolean, value: any}`, where `done=true` means that the iteration is finished, otherwise `value` must be the new value.
@@ -72,9 +73,9 @@ There is an important separation of concerns in this code:
72
73
- The `range` itself does not have the `next()` method.
73
74
- Instead, another object, a so-called "iterator" is created by the call to `range[Symbol.iterator]()`, and it handles the iteration.
74
75
75
-
So, the iterator is separate from the object.
76
+
So, the iterator object is separate from the object it iterates over.
76
77
77
-
Technically, we may merge them and use `range` itself as the iterator, to make the code simpler.
78
+
Technically, we may merge them and use `range` itself as the iterator to make the code simpler.
78
79
79
80
Like this:
80
81
@@ -102,7 +103,7 @@ for (let num of range) {
102
103
}
103
104
```
104
105
105
-
Now `range[Symbol.iterator]()` returns the `range` object itself, and it has the necessary `next()` method. Sometimes that's fine too. 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.
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`. Sometimes that's fine too. 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.
106
107
107
108
```smart header="Infinite iterators"
108
109
Infinite iterators are also doable. For instance, the `range` becomes infinite for `range.to = Infinity`. Or we can make an iterable object that generates an infinite sequence of pseudorandom numbers. Also can be useful.
@@ -138,9 +139,9 @@ for(let char of str) {
138
139
139
140
Normally, internals of iterables are hidden from the external code. There's a `for..of` loop, that works, that's all it needs to know.
140
141
141
-
But to understand things a little bit more deeper let's see how to create an iterator explicitly. We'll do that the same way as `for..of`, but with direct calls.
142
+
But to understand things a little bit more deeper let's see how to create an iterator explicitly.
142
143
143
-
For instance, this code gets a string iterator and calls it "manually":
144
+
We'll iterate over a string the same way as `for..of`, but with direct calls. This code gets a string iterator and calls it "manually":
144
145
145
146
```js run
146
147
let str ="Hello";
@@ -157,16 +158,16 @@ while(true) {
157
158
}
158
159
```
159
160
160
-
That is rarely needed, but gives us more control than `for..of`. For instance, we can split the iteration process: iterate a bit, then stop, do something else, and then resume later.
161
+
That is rarely needed, but gives us more control over the process than `for..of`. For instance, we can split the iteration process: iterate a bit, then stop, do something else, and then resume later.
161
162
162
163
## Iterables and array-likes [#array-like]
163
164
164
-
There are two official terms that look similar, but are very different. Please be careful to avoid the confusion.
165
+
There are two official terms that look similar, but are very different. Please make sure you understand them well to avoid the confusion.
165
166
166
167
-*Iterables* are objects that implement the `Symbol.iterator` method, as described above.
167
168
-*Array-likes* are objects that have indexes and `length`, so they look like arrays.
168
169
169
-
Naturally, they can combine. For instance, strings are both iterable and array-like.
170
+
Naturally, these properties can combine. For instance, strings are both iterable (`for..of` works on them) and array-like (they have numeric indexes and `length`).
170
171
171
172
But an iterable may be not array-like and vice versa.
172
173
@@ -236,7 +237,7 @@ let arr = Array.from(range, num => num * num);
236
237
alert(arr); // 1,4,9,16,25
237
238
```
238
239
239
-
We can also use `Array.from` to turn a string into an array of characters:
240
+
Here we use `Array.from` to turn a string into an array of characters:
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/03-closure/article.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -334,9 +334,9 @@ Here's what's going on in the `makeCounter` example step-by-step, follow it to m
334
334
335
335
3. During the execution of `makeCounter()`, a tiny nested function is created.
336
336
337
-
It doesn't matter whether the function is created using Function Declaration or Function Expression. All functions get the `[[Environment]]` property that references the Lexical Environment where they were made.
337
+
It doesn't matter whether the function is created using Function Declaration or Function Expression. All functions get the `[[Environment]]` property that references the Lexical Environment where they were made. So that new tiny nested function gets it as well.
338
338
339
-
For our new nested function that is the current Lexical Environment of `makeCounter()`:
339
+
For our new nested function the value of `[[Environment]]`is the current Lexical Environment of `makeCounter()` (where it was born):
0 commit comments