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/03-code-quality/01-debugging-chrome/article.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ Before writing more complex code, let's talk about debugging.
4
4
5
5
[Debugging](https://en.wikipedia.org/wiki/Debugging) is the process of finding and fixing errors within a script. All modern browsers and most other environments support debugging tools -- a special UI in developer tools that makes debugging much easier. It also allows to trace the code step by step to see what exactly is going on.
6
6
7
-
We'll be using Chrome here, because it has enough features, most other browsers have a similar process`.
7
+
We'll be using Chrome here, because it has enough features, most other browsers have a similar process.
8
8
9
9
## The "Sources" panel
10
10
@@ -24,11 +24,11 @@ Let's click it and select `hello.js` in the tree view. Here's what should show u
24
24
25
25

26
26
27
-
Here we can see three zones:
27
+
The Sources panel has 3 parts:
28
28
29
-
1. The **Resources zone** lists HTML, JavaScript, CSS and other files, including images that are attached to the page. Chrome extensions may appear here too.
30
-
2. The **Source zone** shows the source code.
31
-
3. The **Information and control zone** is for debugging, we'll explore it soon.
29
+
1. The **File Navigator** pane lists HTML, JavaScript, CSS and other files, including images that are attached to the page. Chrome extensions may appear here too.
30
+
2. The **Code Editor** pane shows the source code.
31
+
3. The **JavaScript Debugging** pane is for debugging, we'll explore it soon.
32
32
33
33
Now you could click the same toggler <spanclass="devtools"style="background-position:-172px-122px"></span> again to hide the resources list and give the code some space.
Copy file name to clipboardExpand all lines: 1-js/05-data-types/07-map-set/article.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,6 +41,12 @@ alert( map.size ); // 3
41
41
42
42
As we can see, unlike objects, keys are not converted to strings. Any type of key is possible.
43
43
44
+
```smart header="`map[key]` isn't the right way to use a `Map`"
45
+
Although `map[key]` also works, e.g. we can set `map[key] = 2`, this is treating `map` as a plain JavaScript object, so it implies all corresponding limitations (no object keys and so on).
46
+
47
+
So we should use `map` methods: `set`, `get` and so on.
Copy file name to clipboardExpand all lines: 1-js/11-async/01-callbacks/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
@@ -109,7 +109,7 @@ loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', s
109
109
110
110
That's called a "callback-based" style of asynchronous programming. A function that does something asynchronously should provide a `callback` argument where we put the function to run after it's complete.
111
111
112
-
Here we did it in `loadScript`, but of course, it's a general approach.
112
+
Here we did it in `loadScript`, but of course it's a general approach.
Copy file name to clipboardExpand all lines: 1-js/11-async/02-promise-basics/article.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,9 +31,9 @@ When the executor obtains the result, be it soon or late - doesn't matter, it sh
31
31
-`resolve(value)` — if the job finished successfully, with result `value`.
32
32
-`reject(error)` — if an error occurred, `error` is the error object.
33
33
34
-
So to summarize: the executor runs automatically, it should do a job, and then call either `resolve` or `reject`.
34
+
So to summarize: the executor runs automatically and performs a job. Then it should call `resolve`if it was succssful or `reject` if there was an error.
35
35
36
-
The `promise` object returned by `new Promise` constructor has internal properties:
36
+
The `promise` object returned by the `new Promise` constructor has internal properties:
37
37
38
38
-`state` — initially `"pending"`, then changes to either `"fulfilled"` when `resolve` is called or `"rejected"` when `reject` is called.
39
39
-`result` — initially `undefined`, then changes to `value` when `resolve(value)` called or `error` when `reject(error)` is called.
@@ -58,7 +58,7 @@ let promise = new Promise(function(resolve, reject) {
58
58
We can see two things by running the code above:
59
59
60
60
1. The executor is called automatically and immediately (by `new Promise`).
61
-
2. The executor receives two arguments: `resolve` and `reject` — these functions are pre-defined by the JavaScript engine. So we don't need to create them. We should only call one of them when ready.
61
+
2. The executor receives two arguments: `resolve` and `reject`. These functions are pre-defined by the JavaScript engine, so we don't need to create them. We should only call one of them when ready.
62
62
63
63
After one second of "processing" the executor calls `resolve("done")` to produce the result. This changes the state of the `promise` object:
64
64
@@ -79,7 +79,7 @@ The call to `reject(...)` moves the promise object to `"rejected"` state:
79
79
80
80

81
81
82
-
To summarize, the executor should do a job (something that takes time usually) and then call `resolve` or `reject` to change the state of the corresponding promise object.
82
+
To summarize, the executor should perform a job (usually something that takes time) and then call `resolve` or `reject` to change the state of the corresponding promise object.
83
83
84
84
A promise that is either resolved or rejected is called "settled", as opposed to an initially "pending" promise.
85
85
@@ -166,7 +166,7 @@ promise.then(
166
166
167
167
The first function was executed.
168
168
169
-
And in the case of a rejection -- the second one:
169
+
And in the case of a rejection, the second one:
170
170
171
171
```js run
172
172
let promise = new Promise(function(resolve, reject) {
@@ -205,7 +205,7 @@ let promise = new Promise((resolve, reject) => {
205
205
});
206
206
207
207
*!*
208
-
// .catch(f) is the same as .then(null, f)
208
+
// .catch(f) is the same as promise.then(null, f)
209
209
promise.catch(alert); // shows "Error: Whoops!" after 1 second
210
210
*/!*
211
211
```
@@ -255,7 +255,7 @@ It's not exactly an alias of `then(f,f)` though. There are several important dif
255
255
})
256
256
.finally(() => alert("Promise ready"))
257
257
.catch(err => alert(err)); // <-- .catch handles the error object
258
-
```
258
+
```
259
259
260
260
That's very convenient, because `finally` is not meant to process a promise result. So it passes it through.
261
261
@@ -303,7 +303,7 @@ Let's rewrite it using Promises.
303
303
The new function `loadScript` will not require a callback. Instead, it will create and return a Promise object that resolves when the loading is complete. The outer code can add handlers (subscribing functions) to it using `.then`:
Copy file name to clipboardExpand all lines: 1-js/11-async/07-microtask-queue/article.md
+15-15Lines changed: 15 additions & 15 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
Promise handlers `.then`/`.catch`/`.finally` are always asynchronous.
5
5
6
-
Even when a Promise is immediately resolved, the code on the lines *below*`.then`/`.catch`/`.finally` will still execute before these handlers.
6
+
Even when a Promise is immediately resolved, the code on the lines *below*`.then`/`.catch`/`.finally` will still execute before these handlers.
7
7
8
-
Here's the demo:
8
+
Here's a demo:
9
9
10
10
```js run
11
11
let promise =Promise.resolve();
@@ -23,22 +23,22 @@ Why did the `.then` trigger afterwards? What's going on?
23
23
24
24
## Microtasks queue
25
25
26
-
Asynchronous tasks need proper management. For that, the standard specifies an internal queue `PromiseJobs`, more often referred to as "microtask queue" (v8 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" (ES8 term).
27
27
28
-
As said in the [specification](https://tc39.github.io/ecma262/#sec-jobs-and-job-queues):
28
+
As stated in the [specification](https://tc39.github.io/ecma262/#sec-jobs-and-job-queues):
29
29
30
30
- The queue is first-in-first-out: tasks enqueued first are run first.
31
31
- Execution of a task is initiated only when nothing else is running.
32
32
33
-
Or, to say that simply, when a promise is ready, its `.then/catch/finally` handlers are put into the queue. They are not executed yet. When the JavaScript engine becomes free from the current code, it takes a task from the queue and executes it.
33
+
Or, to say more simply, when a promise is ready, its `.then/catch/finally` handlers are put into the queue; they are not executed yet. When the JavaScript engine becomes free from the current code, it takes a task from the queue and executes it.
34
34
35
35
That's why "code finished" in the example above shows first.
36
36
37
37

38
38
39
39
Promise handlers always go through this internal queue.
40
40
41
-
If there's a chain with multiple `.then/catch/finally`, then every one of them is executed asynchronously. That is, it first gets queued, and executed when the current code is complete and previously queued handlers are finished.
41
+
If there's a chain with multiple `.then/catch/finally`, then every one of them is executed asynchronously. That is, it first gets queued, then executed when the current code is complete and previously queued handlers are finished.
42
42
43
43
**What if the order matters for us? How can we make `code finished` run after `promise done`?**
44
44
@@ -58,7 +58,7 @@ Remember the `unhandledrejection` event from the chapter <info:promise-error-han
58
58
59
59
Now we can see exactly how JavaScript finds out that there was an unhandled rejection.
60
60
61
-
**"Unhandled rejection" occurs when a promise error is not handled at the end of the microtask queue.**
61
+
**An "unhandled rejection" occurs when a promise error is not handled at the end of the microtask queue.**
62
62
63
63
Normally, if we expect an error, we add `.catch` to the promise chain to handle it:
Now, if you run it, we'll see `Promise Failed!` first and then `caught`.
96
+
Now, if we run it, we'll see `Promise Failed!` first and then `caught`.
97
97
98
-
If we didn't know about the microtasks queue, we could wonder: "Why did `unhandledrejection` handler run? We did catch the error!".
98
+
If we didn't know about the microtasks queue, we could wonder: "Why did `unhandledrejection` handler run? We did catch and handle the error!"
99
99
100
-
But now we understand that `unhandledrejection` is generated when the microtask queue is complete: the engine examines promises and, if any of them is in "rejected" state, then the event triggers.
100
+
But now we understand that `unhandledrejection` is generated when the microtask queue is complete: the engine examines promises and, if any of them is in the "rejected" state, then the event triggers.
101
101
102
-
In the example above, `.catch` added by `setTimeout` also triggers, but later, after `unhandledrejection` has already occurred, so that doesn't change anything.
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.
103
103
104
104
## Summary
105
105
106
-
Promise handling is always asynchronous, as all promise actions pass through the internal "promise jobs" queue, also called "microtask queue" (v8 term).
106
+
Promise handling is always asynchronous, as all promise actions pass through the internal "promise jobs" queue, also called "microtask queue" (ES8 term).
107
107
108
-
So,`.then/catch/finally` handlers are always called after the current code is finished.
108
+
So `.then/catch/finally` handlers are always called after the current code is finished.
109
109
110
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.
111
111
112
-
In most JavaScript engines, including browsers and Node.js, the concept of microtasks is closely tied with "event loop" and "macrotasks". As these have no direct relation to promises, they are covered in another part of the tutorial, in the chapter <info:event-loop>.
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 chapter <info:event-loop>.
The conversion of bigint to number is always silent, but if the bigint is too huge and won't fit the number type, then extra bits will be cut off, causing a precision loss.
48
+
The conversion operations are always silent, never give errors, but if the bigint is too huge and won't fit the number type, then extra bits will be cut off, so we should be careful doing such conversion.
49
49
50
50
````smart header="The unary plus is not supported on bigints"
51
51
The unary plus operator `+value` is a well-known way to convert `value` to a number.
@@ -69,7 +69,7 @@ alert( 2n > 1n ); // true
69
69
alert( 2n>1 ); // true
70
70
```
71
71
72
-
As numbers and bigints belong to different types, they can be equal `==`, but not strictly equal `===`:
72
+
Please note though, as numbers and bigints belong to different types, they can be equal `==`, but not strictly equal `===`:
73
73
74
74
```js run
75
75
alert( 1==1n ); // true
@@ -101,15 +101,15 @@ alert( 0n || 2 ); // 2 (0n is considered falsy)
101
101
102
102
Polyfilling bigints is tricky. The reason is that many JavaScript operators, such as `+`, `-` and so on behave differently with bigints compared to regular numbers.
103
103
104
-
For example, division of bigints always returns an integer.
104
+
For example, division of bigints always returns a bigint (rounded if necessary).
105
105
106
-
To emulate such behavior, a polyfill would need to replace all such operators with its functions. But doing so is cumbersome and would cost a lot of performance.
106
+
To emulate such behavior, a polyfill would need to analyze the code and replace all such operators with its functions. But doing so is cumbersome and would cost a lot of performance.
107
107
108
108
So, there's no well-known good polyfill.
109
109
110
110
Although, the other way around is proposed by the developers of [https://github.com/GoogleChromeLabs/jsbi](JSBI) library.
111
111
112
-
They suggest to use JSBI library calls instead of native bigints:
112
+
This library implements big numbers using its own methods. We can use them instead of native bigints:
113
113
114
114
| Operation | native `BigInt`| JSBI |
115
115
|-----------|-----------------|------|
@@ -120,7 +120,9 @@ They suggest to use JSBI library calls instead of native bigints:
120
120
121
121
...And then use the polyfill (Babel plugin) to convert JSBI calls to native bigints for those browsers that support them.
122
122
123
-
In other words, this approach suggests that we write code in JSBI instead of native bigints. But JSBI works with numbers as with bigints internally, closely following the specification, so the code will be "bigint-ready".
123
+
In other words, this approach suggests that we write code in JSBI instead of native bigints. But JSBI works with numbers as with bigints internally, emulates them closely following the specification, so the code will be "bigint-ready".
124
+
125
+
We can use such JSBI code "as is" for engines that don't support bigints and for those that do support - the polyfill will convert the calls to native bigints.
Copy file name to clipboardExpand all lines: 2-ui/5-loading/03-onload-onerror/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
@@ -107,7 +107,7 @@ That's for historical reasons.
107
107
108
108
There's a rule: scripts from one site can't access contents of the other site. So, e.g. a script at `https://facebook.com` can't read the user's mailbox at `https://gmail.com`.
109
109
110
-
Or, to be more precise, one origin (domain/port/protocol triplet) can't access the content from another one. So even if we have a subdomain, or just another port, these are different origins, no access to each other.
110
+
Or, to be more precise, one origin (domain/port/protocol triplet) can't access the content from another one. So even if we have a subdomain, or just another port, these are different origins with no access to each other.
111
111
112
112
This rule also affects resources from other domains.
113
113
@@ -159,7 +159,7 @@ Details may vary depending on the browser, but the idea is the same: any informa
159
159
160
160
Why do we need error details?
161
161
162
-
There are many services (and we can build our own) that listen for global errors using `window.onerror`, save errors and provide an interface to access and analyze them. That's great, as we can see real errors, triggered by our users. But if a script comes from another origin, then there's no much information about errors in it, as we've just seen.
162
+
There are many services (and we can build our own) that listen for global errors using `window.onerror`, save errors and provide an interface to access and analyze them. That's great, as we can see real errors, triggered by our users. But if a script comes from another origin, then there's not much information about errors in it, as we've just seen.
163
163
164
164
Similar cross-origin policy (CORS) is enforced for other types of resources as well.
0 commit comments