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/01-getting-started/1-intro/article.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -109,8 +109,9 @@ Exemplos de tais linguagens:
109
109
-[CoffeeScript](http://coffeescript.org/) é um "açúcar sintático" para JavaScript. Ele introduz uma sintaxe mais curta, permitindo-nos escrever um código mais claro e preciso. Normalmente, Ruby devs gostam dele.
110
110
-[TypeScript](http://www.typescriptlang.org/) está concentrado em adicionar "estritos tipos de dados" para simplificar o desenvolvimento e suporte de sistemas complexos. É desenvolvido pela Microsoft.
111
111
-[Flow](http://flow.org/) também adiciona tipos de dados, mas de uma forma diferente. Desenvolvido pela Facebook.
112
-
-[Dart](https://www.dartlang.org/) é uma linguagem autônoma que tem seu próprio interpretador que roda em ambientes fora do navegador (como aplicativos móveis), mas também pode ser transpilada para JavaScript. Desenvolvido pela Google.
112
+
-[Dart](https://www.dartlang.org/) é uma linguagem autônoma que tem seu próprio interpretador que roda em ambientes fora do navegador (como aplicativos móveis), mas também pode ser transpilada para JavaScript. Desenvolvida pela Google.
113
113
-[Brython](https://brython.info/) é um transpilador de Python para JavaScript que permite escrever aplicativos em puro Python, sem JavaScript.
114
+
-[Kotlin](https://kotlinlang.org/docs/js-overview.html) é uma linguagem de programação moderna, concisa e segura, que pode ser usada no navegador ou no Node.
114
115
115
116
Há mais. Claro que, mesmo que usemos uma dessas linguagens transpiladas, também devemos saber JavaScript para entender o que estamos fazendo.
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/07-optional-chaining/article.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -219,4 +219,4 @@ As we can see, all of them are straightforward and simple to use. The `?.` check
219
219
220
220
A chain of `?.` allows to safely access nested properties.
221
221
222
-
Still, we should apply `?.` carefully, only where it's acceptable that the left part doesn't to exist. So that it won't hide programming errors from us, if they occur.
222
+
Still, we should apply `?.` carefully, only where it's acceptable that the left part doesn't exist. So that it won't hide programming errors from us, if they occur.
Copy file name to clipboardExpand all lines: 1-js/05-data-types/02-number/article.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ Imagine we need to write 1 billion. The obvious way is:
16
16
let billion =1000000000;
17
17
```
18
18
19
-
But in real life we usually avoid writing a long string of zeroes as it's easy to mistype. Also, we are lazy. We will usually write something like `"1bn"` for a billion or `"7.3bn"` for 7 billion 300 million. The same is true for most large numbers.
19
+
But in real life, we usually avoid writing a long string of zeroes as it's easy to mistype. Also, we are lazy. We will usually write something like `"1bn"` for a billion or `"7.3bn"` for 7 billion 300 million. The same is true for most large numbers.
20
20
21
21
In JavaScript, we shorten a number by appending the letter `"e"` to the number and specifying the zeroes count:
22
22
@@ -180,7 +180,7 @@ There are two ways to do so:
180
180
181
181
## Imprecise calculations
182
182
183
-
Internally, a number is represented in 64-bit format [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point (they are zero for integer numbers), and 1 bit is for the sign.
183
+
Internally, a number is represented in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point (they are zero for integer numbers), and 1 bit is for the sign.
184
184
185
185
If a number is too big, it would overflow the 64-bit storage, potentially giving an infinity:
186
186
@@ -208,15 +208,15 @@ Ouch! There are more consequences than an incorrect comparison here. Imagine you
208
208
209
209
But why does this happen?
210
210
211
-
A number is stored in memory in its binary form, a sequence of ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form.
211
+
A number is stored in memory in its binary form, a sequence of bits - ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form.
212
212
213
213
In other words, what is `0.1`? It is one divided by ten `1/10`, one-tenth. In decimal numeral system such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`.
214
214
215
215
So, division by powers `10` is guaranteed to work well in the decimal system, but division by `3` is not. For the same reason, in the binary numeral system, the division by powers of `2` is guaranteed to work, but `1/10` becomes an endless binary fraction.
216
216
217
217
There's just no way to store *exactly 0.1* or *exactly 0.2* using the binary system, just like there is no way to store one-third as a decimal fraction.
218
218
219
-
The numeric format IEEE-754 solves this by rounding to the nearest possible number. These rounding rules normally don't allow us to see that "tiny precision loss", so the number shows up as `0.3`. But beware, the loss still exists.
219
+
The numeric format IEEE-754 solves this by rounding to the nearest possible number. These rounding rules normally don't allow us to see that "tiny precision loss", but it exists.
220
220
221
221
We can see this in action:
222
222
```js run
@@ -327,7 +327,7 @@ Please note that an empty or a space-only string is treated as `0` in all numeri
327
327
There is a special built-in method [`Object.is`](mdn:js/Object/is) that compares values like `===`, but is more reliable for two edge cases:
328
328
329
329
1. It works with `NaN`: `Object.is(NaN, NaN) === true`, that's a good thing.
330
-
2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, it rarely matters, but these values technically are different.
330
+
2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, technically that's true, because internally the number has a sign bit that may be different even if all other bits are zeroes.
331
331
332
332
In all other cases, `Object.is(a, b)` is the same as `a === b`.
333
333
@@ -383,7 +383,7 @@ JavaScript has a built-in [Math](https://developer.mozilla.org/en/docs/Web/JavaS
383
383
A few examples:
384
384
385
385
`Math.random()`
386
-
: Returns a random number from 0 to 1 (not including 1)
386
+
: Returns a random number from 0 to 1 (not including 1).
Copy file name to clipboardExpand all lines: 1-js/05-data-types/06-iterable/article.md
+11-11Lines changed: 11 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,9 +3,9 @@
3
3
4
4
*Iterable* objects are a generalization of arrays. That's a concept that allows us to make any object useable in a `for..of` loop.
5
5
6
-
Of course, Arrays are iterable. But there are many other built-in objects, that are iterable as well. For instance, Strings are iterable also. As we'll see, many built-in operators and methods rely on them.
6
+
Of course, Arrays are iterable. But there are many other built-in objects, that are iterable as well. For instance, strings are also iterable.
7
7
8
-
If an object 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.
8
+
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.
9
9
10
10
11
11
## Symbol.iterator
@@ -31,9 +31,9 @@ To make the `range` object iterable (and thus let `for..of` work) we need to add
31
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
32
2. Onward, `for..of` works *only with that returned object*.
33
33
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`must be the new value.
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.
35
35
36
-
Here's the full implementation for `range`:
36
+
Here's the full implementation for `range` with remarks:
37
37
38
38
```js run
39
39
let range = {
@@ -68,10 +68,10 @@ for (let num of range) {
68
68
}
69
69
```
70
70
71
-
Please note the core feature of iterables: an important separation of concerns:
71
+
Please note the core feature of iterables: separation of concerns.
72
72
73
73
- The `range` itself does not have the `next()` method.
74
-
- Instead, another object, a so-called "iterator" is created by the call to `range[Symbol.iterator]()`, and it handles the whole iteration.
74
+
- Instead, another object, a so-called "iterator" is created by the call to `range[Symbol.iterator]()`, and its `next()` generates values for the iteration.
75
75
76
76
So, the iterator object is separate from the object it iterates over.
77
77
@@ -105,7 +105,7 @@ for (let num of range) {
105
105
106
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.
107
107
108
-
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, doable with some async scenarios.
108
+
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.
109
109
110
110
```smart header="Infinite iterators"
111
111
Infinite iterators are also possible. 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.
@@ -174,7 +174,7 @@ When we use JavaScript for practical tasks in a browser or any other environment
174
174
175
175
For instance, strings are both iterable (`for..of` works on them) and array-like (they have numeric indexes and `length`).
176
176
177
-
But an iterable may not be array-like. And vice versa an array-like may not be iterable.
177
+
But an iterable may be not array-like. And vice versa an array-like may be not iterable.
178
178
179
179
For example, the `range` in the example above is iterable, but not array-like, because it does not have indexed properties and `length`.
180
180
@@ -193,11 +193,11 @@ for (let item of arrayLike) {}
193
193
*/!*
194
194
```
195
195
196
-
What do they have in common? 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.
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?
197
197
198
198
## Array.from
199
199
200
-
There's a universal method [Array.from](mdn:js/Array/from) that brings them together. It takes an iterable or array-like value and makes a "real" `Array` from it. Then we can call array methods on it.
200
+
There's a universal method [Array.from](mdn:js/Array/from) that takes an iterable or array-like value and makes a "real" `Array` from it. Then we can call array methods on it.
201
201
202
202
For instance:
203
203
@@ -283,7 +283,7 @@ let str = '𝒳😂𩷶';
283
283
284
284
alert( slice(str, 1, 3) ); // 😂𩷶
285
285
286
-
// native method does not support surrogate pairs
286
+
//the native method does not support surrogate pairs
287
287
alert( str.slice(1, 3) ); // garbage (two pieces from different surrogate pairs)
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/04-var/article.md
+15-3Lines changed: 15 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -42,7 +42,19 @@ alert(test); // true, the variable lives after if
42
42
*/!*
43
43
```
44
44
45
-
If we used `let test` on the 2nd line, then it wouldn't be visible to `alert`. But `var` ignores code blocks, so we've got a global `test`.
45
+
As `var` ignores code blocks, we've got a global variable `test`.
46
+
47
+
If we used `let test` instead of `var test`, then the variable would only be visible inside `if`:
48
+
49
+
```js run
50
+
if (true) {
51
+
let test =true; // use "let"
52
+
}
53
+
54
+
*!*
55
+
alert(test); // ReferenceError: test is not defined
56
+
*/!*
57
+
```
46
58
47
59
The same thing for loops: `var` cannot be block- or loop-local:
48
60
@@ -70,7 +82,7 @@ function sayHi() {
70
82
}
71
83
72
84
sayHi();
73
-
alert(phrase); //Error: phrase is not defined
85
+
alert(phrase); //ReferenceError: phrase is not defined
74
86
```
75
87
76
88
As we can see, `var` pierces through `if`, `for` or other code blocks. That's because a long time ago in JavaScript, blocks had no Lexical Environments, and `var` is a remnant of that.
@@ -216,7 +228,7 @@ The Function Expression is wrapped with parenthesis `(function {...})`, because
216
228
217
229
```js run
218
230
// Tries to declare and immediately call a function
219
-
function() { // <-- Error: Function statements require a function name
231
+
function() { // <-- SyntaxError: Function statements require a function name
Promise handlers `.then`/`.catch`/`.finally` are always asynchronous.
5
5
@@ -10,20 +10,20 @@ Here's a demo:
10
10
```js run
11
11
let promise =Promise.resolve();
12
12
13
-
promise.then(() =>alert("promise done"));
13
+
promise.then(() =>alert("promise done!"));
14
14
15
15
alert("code finished"); // this alert shows first
16
16
```
17
17
18
-
If you run it, you see `code finished` first, and then `promise done`.
18
+
If you run it, you see `code finished` first, and then `promise done!`.
19
19
20
20
That's strange, because the promise is definitely done from the beginning.
21
21
22
22
Why did the `.then` trigger afterwards? What's going on?
23
23
24
-
# Microtasks
24
+
##Microtasks queue
25
25
26
-
Asynchronous tasks need proper management. For that, the ECMA standard specifies an internal queue `PromiseJobs`, more often referred to as the "microtask queue" (ES8 term).
26
+
Asynchronous tasks need proper management. For that, the ECMA standard specifies an internal queue `PromiseJobs`, more often referred to as the "microtask queue" (V8 term).
27
27
28
28
As stated in the [specification](https://tc39.github.io/ecma262/#sec-jobs-and-job-queues):
29
29
@@ -52,77 +52,6 @@ Promise.resolve()
52
52
53
53
Now the order is as intended.
54
54
55
-
## Event loop
56
-
57
-
In-browser JavaScript, as well as Node.js, is based on an *event loop*.
58
-
59
-
"Event loop" is a process when the engine sleeps and waits for events, then reacts on those and sleeps again.
60
-
61
-
Examples of events:
62
-
-`mousemove`, a user moved their mouse.
63
-
-`setTimeout` handler is to be called.
64
-
- an external `<script src="...">` is loaded, ready to be executed.
65
-
- a network operation, e.g. `fetch` is complete.
66
-
- ...etc.
67
-
68
-
Things happen -- the engine handles them -- and waits for more to happen (while sleeping and consuming close to zero CPU).
69
-
70
-

71
-
72
-
As you can see, there's also a queue here. A so-called "macrotask queue" (v8 term).
73
-
74
-
When an event happens, while the engine is busy, its handling is enqueued.
75
-
76
-
For instance, while the engine is busy processing a network `fetch`, a user may move their mouse causing `mousemove`, and `setTimeout` may be due and so on, just as painted on the picture above.
77
-
78
-
Events from the macrotask queue are processed on "first come – first served" basis. When the engine browser finishes with `fetch`, it handles `mousemove` event, then `setTimeout` handler, and so on.
79
-
80
-
So far, quite simple, right? The engine is busy, so other tasks queue up.
81
-
82
-
Now the important stuff.
83
-
84
-
**Microtask queue has a higher priority than the macrotask queue.**
85
-
86
-
In other words, the engine first executes all microtasks, and then takes a macrotask. Promise handling always has the priority.
87
-
88
-
For instance, take a look:
89
-
90
-
```js run
91
-
setTimeout(() =>alert("timeout"));
92
-
93
-
Promise.resolve()
94
-
.then(() =>alert("promise"));
95
-
96
-
alert("code");
97
-
```
98
-
99
-
What's the order?
100
-
101
-
1.`code` shows first, because it's a regular synchronous call.
102
-
2.`promise` shows second, because `.then` passes through the microtask queue, and runs after the current code.
103
-
3.`timeout` shows last, because it's a macrotask.
104
-
105
-
It may happen that while handling a macrotask, new promises are created.
106
-
107
-
Or, vice-versa, a microtask schedules a macrotask (e.g. `setTimeout`).
108
-
109
-
For instance, here `.then` schedules a `setTimeout`:
110
-
111
-
```js run
112
-
Promise.resolve()
113
-
.then(() => {
114
-
setTimeout(() =>alert("timeout"), 0);
115
-
})
116
-
.then(() => {
117
-
alert("promise");
118
-
});
119
-
```
120
-
121
-
Naturally, `promise` shows up first, because `setTimeout` macrotask awaits in the less-priority macrotask queue.
122
-
123
-
As a logical consequence, macrotasks are handled only when promises give the engine a "free time". So if we have a promise chain that doesn't wait for anything, then things like `setTimeout` or event handlers can never get in the middle.
124
-
125
-
126
55
## Unhandled rejection
127
56
128
57
Remember the `unhandledrejection` event from the article <info:promise-error-handling>?
@@ -131,34 +60,33 @@ Now we can see exactly how JavaScript finds out that there was an unhandled reje
131
60
132
61
**An "unhandled rejection" occurs when a promise error is not handled at the end of the microtask queue.**
133
62
134
-
For instance, consider this code:
63
+
Normally, if we expect an error, we add `.catch` to the promise chain to handle it:
135
64
136
65
```js run
137
66
let promise =Promise.reject(newError("Promise Failed!"));
@@ -173,16 +101,12 @@ But now we understand that `unhandledrejection` is generated when the microtask
173
101
174
102
In the example above, `.catch` added by `setTimeout` also triggers. But it does so later, after `unhandledrejection` has already occurred, so it doesn't change anything.
175
103
176
-
**So, `.then/catch/finally` are called after the current code is finished.**
177
-
178
-
If we need to guarantee that a piece of code is executed after `.then/catch/finally`, it's best to add it into a chained `.then` call.
179
-
180
-
- There's also a "macrotask queue" that keeps various events, network operation results, `setTimeout`-scheduled calls, and so on. These are also called "macrotasks" (v8 term).
104
+
## Summary
181
105
182
-
Promise handling is always asynchronous, as all promise actions pass through the internal "promise jobs" queue, also called "microtask queue" (ES8 term).
106
+
Promise handling is always asynchronous, as all promise actions pass through the internal "promise jobs" queue, also called "microtask queue" (V8 term).
183
107
184
108
So `.then/catch/finally` handlers are always called after the current code is finished.
185
109
186
-
In other words, they have lower priority.
110
+
If we need to guarantee that a piece of code is executed after `.then/catch/finally`, we can add it into a chained `.then` call.
187
111
188
112
In most Javascript engines, including browsers and Node.js, the concept of microtasks is closely tied with the "event loop" and "macrotasks". As these have no direct relation to promises, they are covered in another part of the tutorial, in the article <info:event-loop>.
0 commit comments