Skip to content

Commit 3101879

Browse files
authored
Merge pull request #17 from javascript-tutorial/sync-9cb33f40
Sync with upstream @ 9cb33f4
2 parents 0295170 + 4e48f4f commit 3101879

File tree

14 files changed

+120
-93
lines changed

14 files changed

+120
-93
lines changed

1-js/02-first-steps/03-strict-mode/article.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,21 @@ Parfois, lorsque `use strict` fait une différence, vous obtenez des résultats
5454
5555
Même si nous appuyons sur la touche `key:Shift+Entrée` pour saisir plusieurs lignes et que `use strict` est placé en haut, cela ne fonctionne pas. Cela est dû à la manière dont la console exécute le code en interne.
5656
57+
<<<<<<< HEAD
5758
Le moyen fiable pour vous assurer d'utiliser `use strict` serait de saisir le code dans la console de la manière suivante :
59+
=======
60+
You can try to press `key:Shift+Enter` to input multiple lines, and put `use strict` on top, like this:
61+
62+
```js
63+
'use strict'; <Shift+Enter for a newline>
64+
// ...your code
65+
<Enter to run>
66+
```
67+
68+
It works in most browsers, namely Firefox and Chrome.
69+
70+
If it doesn't, the most reliable way to ensure `use strict` would be to input the code into console like this:
71+
>>>>>>> 9cb33f4039e5751bfd0e2bca565a37aa463fb477
5872
5973
```js
6074
(function() {

1-js/03-code-quality/04-ninja-code/article.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,11 @@ Au lieu de cela, réutilisez les noms existants. Il suffit d'écrire de nouvelle
136136

137137
Dans une fonction, n'utilisez que des variables passées en paramètres.
138138

139+
<<<<<<< HEAD
139140
Cela rendrait vraiment difficile d’identifier ce qui est exactement dans la variable maintenant. Et aussi d'où ça vient. Une personne ayant une faible intuition devrait analyser le code ligne par ligne et suivre les modifications dans chaque branche de code.
141+
=======
142+
That would make it really hard to identify what's exactly in the variable *now*. And also where it comes from. The purpose is to develop the intuition and memory of a person reading the code. A person with weak intuition would have to analyze the code line-by-line and track the changes through every code branch.
143+
>>>>>>> 9cb33f4039e5751bfd0e2bca565a37aa463fb477
140144
141145
**Une variante avancée de l'approche consiste à remplacer secrètement (!) La valeur par quelque chose de similaire au milieu d'une boucle ou d'une fonction.**
142146

@@ -154,7 +158,11 @@ function ninjaFunction(elem) {
154158

155159
Un collègue programmeur qui veut travailler avec `elem` dans la seconde moitié de la fonction sera surpris… Seulement lors du débogage, après avoir examiné le code, ils découvrira qu’il travaille avec un clone !
156160

161+
<<<<<<< HEAD
157162
Mortellement efficace même contre un ninja expérimenté. Vu dans du code régulièrement.
163+
=======
164+
Seen in code regularly. Deadly effective even against an experienced ninja.
165+
>>>>>>> 9cb33f4039e5751bfd0e2bca565a37aa463fb477
158166
159167
## Underscores for fun
160168

@@ -168,16 +176,27 @@ Un ninja intelligent place les traits de soulignement à un endroit du code et l
168176

169177
Laissez tout le monde voir à quel point vos entités sont magnifiques! Des noms comme `superElement`, `megaFrame` et `niceItem` illumineront définitivement le lecteur.
170178

179+
<<<<<<< HEAD
171180
En effet, d’une part, quelque chose s’écrit: `super ..`, `mega ..`, `nice ..`. Mais de l’autre -- cela n’apporte aucun détail. Un lecteur peut décider de chercher un sens caché et de méditer pendant une heure ou deux.
172181

173182
## Chevaucher des variables externes
183+
=======
184+
Indeed, from one hand, something is written: `super..`, `mega..`, `nice..` But from the other hand -- that brings no details. A reader may decide to look for a hidden meaning and meditate for an hour or two of their paid working time.
185+
186+
187+
## Overlap outer variables
188+
>>>>>>> 9cb33f4039e5751bfd0e2bca565a37aa463fb477
174189
175190
```quote author="Guan Yin Zi"
176191
Lorsqu'on est dans la lumière, on ne peut rien voir dans l’obscurité.<br>
177192
Lorsqu'on est dans l'obscurité, on peut tout voir dans la lumière.
178193
```
179194

195+
<<<<<<< HEAD
180196
Utilisez les mêmes noms pour les variables à l'intérieur et à l'extérieur d'une fonction. Aussi simple. Aucun effort requis.
197+
=======
198+
Use same names for variables inside and outside a function. As simple. No efforts to invent new names.
199+
>>>>>>> 9cb33f4039e5751bfd0e2bca565a37aa463fb477
181200
182201
```js
183202
let *!*user*/!* = authenticateUser();

1-js/06-advanced-functions/11-currying-partials/article.md

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ To understand the benefits we definitely need a worthy real-life example.
170170

171171
Advanced currying allows the function to be both callable normally and partially.
172172

173-
For instance, we have the logging function `log(date, importance, message)` that formats and outputs the information. In real projects such functions also have many other useful features like sending logs over the network:
173+
For instance, we have the logging function `log(date, importance, message)` that formats and outputs the information. In real projects such functions also have many other useful features like sending logs over the network, here we just use `alert`:
174174

175175
```js
176176
function log(date, importance, message) {
@@ -184,34 +184,29 @@ Let's curry it!
184184
log = _.curry(log);
185185
```
186186

187-
After that `log` still works the normal way:
188-
189-
```js
190-
log(new Date(), "DEBUG", "some debug");
191-
```
192-
193-
...But also can be called in the curried form:
187+
After that `log` work both the normal way and in the curried form:
194188

195189
```js
190+
log(new Date(), "DEBUG", "some debug"); // log(a,b,c)
196191
log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)
197192
```
198193

199-
Let's get a convenience function for today's logs:
194+
Now we can easily make a convenience function for current logs:
200195

201196
```js
202-
// todayLog will be the partial of log with fixed first argument
203-
let todayLog = log(new Date());
197+
// currentLog will be the partial of log with fixed first argument
198+
let currentLog = log(new Date());
204199

205200
// use it
206-
todayLog("INFO", "message"); // [HH:mm] INFO message
201+
currentLog("INFO", "message"); // [HH:mm] INFO message
207202
```
208203

209-
And now a convenience function for today's debug messages:
204+
And here's a convenience function for current debug messages:
210205

211206
```js
212-
let todayDebug = todayLog("DEBUG");
207+
let todayDebug = currentLog("DEBUG");
213208

214-
todayDebug("message"); // [HH:mm] DEBUG message
209+
currentLog("message"); // [HH:mm] DEBUG message
215210
```
216211

217212
So:

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ The good thing is: a `.then` handler is guaranteed to run whether the promise ta
278278

279279
Next, let's see more practical examples of how promises can help us to write asynchronous code.
280280

281-
## Example: loadScript
281+
## Example: loadScript [#loadscript]
282282

283283
We've got the `loadScript` function for loading a script from the previous chapter.
284284

1-js/11-async/03-promise-chaining/article.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ Returning promises allows us to build chains of asynchronous actions.
146146

147147
## Example: loadScript
148148

149-
Let's use this feature with `loadScript` to load scripts one by one, in sequence:
149+
Let's use this feature with the promisified `loadScript`, defined in the [previous chapter](/promise-basics#loadscript), to load scripts one by one, in sequence:
150150

151151
```js run
152152
loadScript("/article/promise-chaining/one.js")
@@ -305,7 +305,7 @@ fetch('/article/promise-chaining/user.json')
305305
});
306306
```
307307

308-
The code works, see comments about the details, but it should be quite self-descriptive. Although, there's a potential problem in it, a typical error of those who begin to use promises.
308+
The code works, see comments about the details. Although, there's a potential problem in it, a typical error of those who begin to use promises.
309309

310310
Look at the line `(*)`: how can we do something *after* the avatar has finished showing and gets removed? For instance, we'd like to show a form for editing that user or something else. As of now, there's no way.
311311

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ Naturally, `promise` shows up first, because `setTimeout` macrotask awaits in th
124124

125125
As a logical consequence, macrotasks are handled only when promises give the engine a "free time". So if we have a chain of promise handlers that don't wait for anything, execute right one after another, then a `setTimeout` (or a user action handler) can never run in-between them.
126126

127-
128127
## Unhandled rejection
129128

130129
Remember "unhandled rejection" event from the chapter <info:promise-error-handling>?

1-js/12-generators-iterators/2-async-iterators-generators/article.md

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

44
Asynchronous iterators allow to iterate over data that comes asynchronously, on-demand.
55

6-
For instance, when we download something chunk-by-chunk, or just expect events to come asynchronously and would like to iterate over them -- async iterators and generators may come in handy. Let's see a simple example first, to grasp the syntax, and then review a real-life use case.
6+
For instance, when we download something chunk-by-chunk, and expect data fragments to come asynchronously and would like to iterate over them -- async iterators and generators may come in handy. Let's see a simple example first, to grasp the syntax, and then review a real-life use case.
77

88
## Async iterators
99

10-
Asynchronous iterators are totally similar to regular iterators, with a few syntactic differences.
10+
Asynchronous iterators are similar to regular iterators, with a few syntactic differences.
1111

12-
"Regular" iterable object from the chapter <info:iterable> look like this:
12+
"Regular" iterable object, as described in the chapter <info:iterable>, look like this:
1313

1414
```js run
1515
let range = {
@@ -101,7 +101,7 @@ let range = {
101101
})()
102102
```
103103

104-
As we can see, the components are similar to regular iterators:
104+
As we can see, the structure is similar to regular iterators:
105105

106106
1. To make an object asynchronously iterable, it must have a method `Symbol.asyncIterator` `(1)`.
107107
2. It must return the object with `next()` method returning a promise `(2)`.
@@ -117,22 +117,22 @@ Here's a small cheatsheet:
117117
| to loop, use | `for..of` | `for await..of` |
118118

119119

120-
````warn header="The spread operator doesn't work asynchronously"
120+
````warn header="The spread operator ... doesn't work asynchronously"
121121
Features that require regular, synchronous iterators, don't work with asynchronous ones.
122122
123123
For instance, a spread operator won't work:
124124
```js
125125
alert( [...range] ); // Error, no Symbol.iterator
126126
```
127127
128-
That's natural, as it expects to find `Symbol.iterator`, same as `for..of` without `await`.
128+
That's natural, as it expects to find `Symbol.iterator`, same as `for..of` without `await`. Not `Symbol.asyncIterator`.
129129
````
130130

131131
## Async generators
132132

133-
JavaScript also provides generators, that are also iterable.
133+
As we already know, JavaScript also supprots generators, and they are iterable.
134134

135-
Let's recall a sequence generator from the chapter [](info:generators). It generates a sequence of values from `start` to `end` (could be anything else):
135+
Let's recall a sequence generator from the chapter [](info:generators). It generates a sequence of values from `start` to `end`:
136136

137137
```js run
138138
function* generateSequence(start, end) {
@@ -147,7 +147,7 @@ for(let value of generateSequence(1, 5)) {
147147
```
148148

149149

150-
Normally, we can't use `await` in generators. All values must come synchronously: there's no place for delay in `for..of`.
150+
Normally, we can't use `await` in generators. All values must come synchronously: there's no place for delay in `for..of`, it's a synchronous construct.
151151

152152
But what if we need to use `await` in the generator body? To perform network requests, for instance.
153153

@@ -184,15 +184,15 @@ It's indeed very simple. We add the `async` keyword, and the generator now can u
184184

185185
Technically, another the difference of an async generator is that its `generator.next()` method is now asynchronous also, it returns promises.
186186

187-
Instead of `result = generator.next()` for a regular, non-async generator, values can be obtained like this:
187+
In a regular generator we'd use `result = generator.next()` to get values. In an async generator, we should add `await`, like this:
188188

189189
```js
190190
result = await generator.next(); // result = {value: ..., done: true/false}
191191
```
192192

193193
## Iterables via async generators
194194

195-
When we'd like to make an object iterable, we should add `Symbol.iterator` to it.
195+
As we already know, to make an object iterable, we should add `Symbol.iterator` to it.
196196

197197
```js
198198
let range = {
@@ -270,7 +270,7 @@ The pattern is very common, it's not about users, but just about anything. For i
270270
- It responds with a JSON of 30 commits, and also provides a link to the next page in the `Link` header.
271271
- Then we can use that link for the next request, to get more commits, and so on.
272272

273-
What we'd like to have is an iterable source of commits, so that we could use it like this:
273+
What we'd like to have is a simpler API: an iterable object with commits, so that we could go over them like this:
274274

275275
```js
276276
let repo = 'javascript-tutorial/en.javascript.info'; // GitHub repository to get commits from
@@ -332,7 +332,7 @@ An example of use (shows commit authors in console):
332332
})();
333333
```
334334

335-
That's just what we wanted. The internal pagination mechanics is invisible from the outside. For us it's just an async generator that returns commits.
335+
That's just what we wanted. The internal mechanics of paginated requests is invisible from the outside. For us it's just an async generator that returns commits.
336336

337337
## Summary
338338

@@ -356,6 +356,6 @@ Syntax differences between async and regular generators:
356356

357357
In web-development we often meet streams of data, when it flows chunk-by-chunk. For instance, downloading or uploading a big file.
358358

359-
We could use async generators to process such data, but there's also another API called Streams, that may be more convenient, as it provides special interfaces to transform the data and to pass it from one stream to another (e.g. download from one place and immediately send elsewhere). But they are also more complex.
359+
We can use async generators to process such data, but it's worth to mention that there's also another API called Streams, that provides special interfaces to transform the data and to pass it from one stream to another (e.g. download from one place and immediately send elsewhere).
360360

361361
Streams API not a part of JavaScript language standard. Streams and async generators complement each other, both are great ways to handle async data flows.

2-ui/1-document/08-styles-and-classes/article.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ So we can operate both on the full class string using `className` or on individu
6666
Methods of `classList`:
6767

6868
- `elem.classList.add/remove("class")` -- adds/removes the class.
69-
- `elem.classList.toggle("class")` -- if the class exists, then removes it, otherwise adds it.
69+
- `elem.classList.toggle("class")` -- adds the class if it doesn't exist, otherwise removes it.
7070
- `elem.classList.contains("class")` -- returns `true/false`, checks for the given class.
7171

72-
Besides that, `classList` is iterable, so we can list all classes like this:
72+
Besides, `classList` is iterable, so we can list all classes with `for..of`, like this:
7373

7474
```html run
7575
<body class="main page">
@@ -147,7 +147,7 @@ To set the full style as a string, there's a special property `style.cssText`:
147147
</script>
148148
```
149149

150-
We rarely use it, because such assignment removes all existing styles: it does not add, but replaces them. May occasionally delete something needed. But still can be done for new elements when we know we won't delete something important.
150+
This property is rarely used, because such assignment removes all existing styles: it does not add, but replaces them. May occasionally delete something needed. But we can safely use it for new elements, when we know we won't delete an existing style.
151151

152152
The same can be accomplished by setting an attribute: `div.setAttribute('style', 'color: red...')`.
153153
````

2-ui/2-events/03-event-delegation/4-behavior-tooltip/task.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Should work like this:
1818

1919
[iframe src="solution" height=200 border=1]
2020

21-
In this task we assume that all elements with `data-tooltip` have only text inside. No nested tags.
21+
In this task we assume that all elements with `data-tooltip` have only text inside. No nested tags (yet).
2222

2323
Details:
2424

@@ -33,4 +33,4 @@ Please use event delegation: set up two handlers on `document` to track all "ove
3333

3434
After the behavior is implemented, even people unfamiliar with JavaScript can add annotated elements.
3535

36-
P.S. To keep things natural and simple: only one tooltip may show up at a time.
36+
P.S. Only one tooltip may show up at a time.

2-ui/2-events/03-event-delegation/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ The pattern has two parts:
182182

183183
### Counter
184184

185-
For instance, here the attribute `data-counter` adds a behavior: "increase on click" to buttons:
185+
For instance, here the attribute `data-counter` adds a behavior: "increase value on click" to buttons:
186186

187187
```html run autorun height=60
188188
Counter: <input type="button" value="1" data-counter>

2-ui/5-loading/02-script-async-defer/article.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,11 @@ But there are also essential differences between them:
188188
| `defer` | *Document order* (as they go in the document). | Execute after the document is loaded and parsed (they wait if needed), right before `DOMContentLoaded`. |
189189

190190
```warn header="Page without scripts should be usable"
191-
Please note that if you're using `defer`, then the page is visible before the script loads and enables all the graphical components.
191+
Please note that if you're using `defer`, then the page is visible *before* the script loads.
192192
193-
So, buttons should be disabled by CSS or by other means, to let the user
193+
So the user may read the page, but some graphical components are probably not ready yet.
194+
195+
There should be "loading" indication in proper places, not-working buttons disabled, to clearly show the user what's ready and what's not.
196+
```
194197

195198
In practice, `defer` is used for scripts that need the whole DOM and/or their relative execution order is important. And `async` is used for independent scripts, like counters or ads. And their relative execution order does not matter.

6-data-storage/02-localstorage/article.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ localStorage.setItem('test', 1);
4242
alert( localStorage.getItem('test') ); // 1
4343
```
4444

45-
We only have to be on the same domain/port/protocol, the url path can be different.
45+
We only have to be on the same origin (domain/port/protocol), the url path can be different.
4646

47-
The `localStorage` is shared, so if we set the data in one window, the change becomes visible in the other one.
47+
The `localStorage` is shared between all windows with the same origin, so if we set the data in one window, the change becomes visible in another one.
4848

4949
## Object-like access
5050

@@ -73,7 +73,7 @@ That's allowed for historical reasons, and mostly works, but generally not recom
7373

7474
## Looping over keys
7575

76-
As we've seen, the methods provide get/set/remove functionality. But how to get all saved values or keys?
76+
As we've seen, the methods provide "get/set/remove by key" functionality. But how to get all saved values or keys?
7777
7878
Unfortunately, storage objects are not iterable.
7979
@@ -198,7 +198,7 @@ Imagine, you have two windows with the same site in each. So `localStorage` is s
198198
You might want to open this page in two browser windows to test the code below.
199199
```
200200

201-
Now if both windows are listening for `window.onstorage`, then each one will react on updates that happened in the other one.
201+
If both windows are listening for `window.onstorage`, then each one will react on updates that happened in the other one.
202202

203203
```js run
204204
// triggers on updates made to the same storage from other documents
@@ -229,18 +229,18 @@ Web storage objects `localStorage` and `sessionStorage` allow to store key/value
229229
| `localStorage` | `sessionStorage` |
230230
|----------------|------------------|
231231
| Shared between all tabs and windows with the same origin | Visible within a browser tab, including iframes from the same origin |
232-
| Survives browser restart | Dies on tab close |
232+
| Survives browser restart | Survives page refresh (but not tab close) |
233233

234234
API:
235235

236236
- `setItem(key, value)` -- store key/value pair.
237237
- `getItem(key)` -- get the value by key.
238238
- `removeItem(key)` -- remove the key with its value.
239239
- `clear()` -- delete everything.
240-
- `key(index)` -- get the key on a given position.
240+
- `key(index)` -- get the key number `index`.
241241
- `length` -- the number of stored items.
242242
- Use `Object.keys` to get all keys.
243-
- Can use the keys as object properties, in that case `storage` event isn't triggered.
243+
- We access keys as object properties, in that case `storage` event isn't triggered.
244244
245245
Storage event:
246246

0 commit comments

Comments
 (0)