Skip to content

Commit a9816b9

Browse files
committed
Merge branch 'master' of github.com:javascript-tutorial/en.javascript.info into sync-db3b3f8e
2 parents 3bfd90a + db3b3f8 commit a9816b9

File tree

17 files changed

+83
-68
lines changed

17 files changed

+83
-68
lines changed

1-js/02-first-steps/14-function-basics/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ There may be many occurrences of `return` in a single function. For instance:
266266
267267
```js run
268268
function checkAge(age) {
269-
if (age > 18) {
269+
if (age >= 18) {
270270
*!*
271271
return true;
272272
*/!*

1-js/03-code-quality/01-debugging-chrome/article.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Before writing more complex code, let's talk about debugging.
44

55
[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.
66

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.
88

99
## The "Sources" panel
1010

@@ -24,11 +24,11 @@ Let's click it and select `hello.js` in the tree view. Here's what should show u
2424

2525
![](chrome-tabs.svg)
2626

27-
Here we can see three zones:
27+
The Sources panel has 3 parts:
2828

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.
3232

3333
Now you could click the same toggler <span class="devtools" style="background-position:-172px -122px"></span> again to hide the resources list and give the code some space.
3434

1-js/05-data-types/07-map-set/article.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ alert( map.size ); // 3
4141

4242
As we can see, unlike objects, keys are not converted to strings. Any type of key is possible.
4343

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.
48+
```
49+
4450
**Map can also use objects as keys.**
4551
4652
For instance:

1-js/07-object-properties/02-property-accessors/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ alert(user.fullName); // John Smith
134134
for(let key in user) alert(key); // name, surname
135135
```
136136

137-
Please note once again that a property can be either an accessor (has `get/set` methods) or a data property (has a `value`), not both.
137+
Please note that a property can be either an accessor (has `get/set` methods) or a data property (has a `value`), not both.
138138

139139
If we try to supply both `get` and `value` in the same descriptor, there will be an error:
140140

1-js/11-async/01-callbacks/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', s
109109

110110
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.
111111

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.
113113

114114
## Callback in callback
115115

1-js/11-async/02-promise-basics/article.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ When the executor obtains the result, be it soon or late - doesn't matter, it sh
3131
- `resolve(value)` — if the job finished successfully, with result `value`.
3232
- `reject(error)` — if an error occurred, `error` is the error object.
3333

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.
3535

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:
3737

3838
- `state` — initially `"pending"`, then changes to either `"fulfilled"` when `resolve` is called or `"rejected"` when `reject` is called.
3939
- `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) {
5858
We can see two things by running the code above:
5959

6060
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.
6262

6363
After one second of "processing" the executor calls `resolve("done")` to produce the result. This changes the state of the `promise` object:
6464

@@ -79,7 +79,7 @@ The call to `reject(...)` moves the promise object to `"rejected"` state:
7979

8080
![](promise-reject-1.svg)
8181

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.
8383

8484
A promise that is either resolved or rejected is called "settled", as opposed to an initially "pending" promise.
8585

@@ -166,7 +166,7 @@ promise.then(
166166
167167
The first function was executed.
168168
169-
And in the case of a rejection -- the second one:
169+
And in the case of a rejection, the second one:
170170
171171
```js run
172172
let promise = new Promise(function(resolve, reject) {
@@ -205,7 +205,7 @@ let promise = new Promise((resolve, reject) => {
205205
});
206206
207207
*!*
208-
// .catch(f) is the same as .then(null, f)
208+
// .catch(f) is the same as promise.then(null, f)
209209
promise.catch(alert); // shows "Error: Whoops!" after 1 second
210210
*/!*
211211
```
@@ -255,7 +255,7 @@ It's not exactly an alias of `then(f,f)` though. There are several important dif
255255
})
256256
.finally(() => alert("Promise ready"))
257257
.catch(err => alert(err)); // <-- .catch handles the error object
258-
```
258+
```
259259
260260
That's very convenient, because `finally` is not meant to process a promise result. So it passes it through.
261261
@@ -303,7 +303,7 @@ Let's rewrite it using Promises.
303303
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`:
304304

305305
```js run
306-
function loadScript(src) {
306+
function loadScript(src) {
307307
return new Promise(function(resolve, reject) {
308308
let script = document.createElement('script');
309309
script.src = src;

1-js/11-async/07-microtask-queue/article.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
Promise handlers `.then`/`.catch`/`.finally` are always asynchronous.
55

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.
77

8-
Here's the demo:
8+
Here's a demo:
99

1010
```js run
1111
let promise = Promise.resolve();
@@ -23,22 +23,22 @@ Why did the `.then` trigger afterwards? What's going on?
2323

2424
## Microtasks queue
2525

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).
2727

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):
2929

3030
- The queue is first-in-first-out: tasks enqueued first are run first.
3131
- Execution of a task is initiated only when nothing else is running.
3232

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.
3434

3535
That's why "code finished" in the example above shows first.
3636

3737
![](promiseQueue.svg)
3838

3939
Promise handlers always go through this internal queue.
4040

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.
4242

4343
**What if the order matters for us? How can we make `code finished` run after `promise done`?**
4444

@@ -58,7 +58,7 @@ Remember the `unhandledrejection` event from the chapter <info:promise-error-han
5858

5959
Now we can see exactly how JavaScript finds out that there was an unhandled rejection.
6060

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.**
6262

6363
Normally, if we expect an error, we add `.catch` to the promise chain to handle it:
6464

@@ -72,7 +72,7 @@ promise.catch(err => alert('caught'));
7272
window.addEventListener('unhandledrejection', event => alert(event.reason));
7373
```
7474

75-
...But if we forget to add `.catch`, then, after the microtask queue is empty, the engine triggers the event:
75+
But if we forget to add `.catch`, then, after the microtask queue is empty, the engine triggers the event:
7676

7777
```js run
7878
let promise = Promise.reject(new Error("Promise Failed!"));
@@ -93,20 +93,20 @@ setTimeout(() => promise.catch(err => alert('caught')), 1000);
9393
window.addEventListener('unhandledrejection', event => alert(event.reason));
9494
```
9595

96-
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`.
9797

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!"
9999

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.
101101

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.
103103

104104
## Summary
105105

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).
107107

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.
109109

110110
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.
111111

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>.

1-js/99-js-misc/05-bigint/article.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ alert(bigint + BigInt(number)); // 3
4545
alert(Number(bigint) + number); // 3
4646
```
4747

48-
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.
4949

5050
````smart header="The unary plus is not supported on bigints"
5151
The unary plus operator `+value` is a well-known way to convert `value` to a number.
@@ -69,7 +69,7 @@ alert( 2n > 1n ); // true
6969
alert( 2n > 1 ); // true
7070
```
7171

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 `===`:
7373

7474
```js run
7575
alert( 1 == 1n ); // true
@@ -101,15 +101,15 @@ alert( 0n || 2 ); // 2 (0n is considered falsy)
101101

102102
Polyfilling bigints is tricky. The reason is that many JavaScript operators, such as `+`, `-` and so on behave differently with bigints compared to regular numbers.
103103

104-
For example, division of bigints always returns an integer.
104+
For example, division of bigints always returns a bigint (rounded if necessary).
105105

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.
107107

108108
So, there's no well-known good polyfill.
109109

110110
Although, the other way around is proposed by the developers of [https://github.com/GoogleChromeLabs/jsbi](JSBI) library.
111111

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:
113113

114114
| Operation | native `BigInt` | JSBI |
115115
|-----------|-----------------|------|
@@ -120,7 +120,9 @@ They suggest to use JSBI library calls instead of native bigints:
120120

121121
...And then use the polyfill (Babel plugin) to convert JSBI calls to native bigints for those browsers that support them.
122122

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.
124126

125127
## References
126128

2-ui/5-loading/03-onload-onerror/article.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ That's for historical reasons.
107107

108108
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`.
109109

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.
111111

112112
This rule also affects resources from other domains.
113113

@@ -159,7 +159,7 @@ Details may vary depending on the browser, but the idea is the same: any informa
159159

160160
Why do we need error details?
161161

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.
163163

164164
Similar cross-origin policy (CORS) is enforced for other types of resources as well.
165165

0 commit comments

Comments
 (0)