Skip to content

Commit 935a053

Browse files
committed
Merge branch 'master' of github.com:javascript-tutorial/en.javascript.info into sync-10c7807f
2 parents da7e723 + 10c7807 commit 935a053

File tree

18 files changed

+109
-121
lines changed

18 files changed

+109
-121
lines changed

1-js/02-first-steps/02-structure/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ But it should be two separate statements, not one. Such a merging in this case i
9494

9595
We recommend putting semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer -- especially for a beginner -- to use them.
9696

97-
## Comments
97+
## Comments [#code-comments]
9898

9999
As time goes on, programs become more and more complex. It becomes necessary to add *comments* which describe what the code does and why.
100100

1-js/04-object-basics/01-object/article.md

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ For multiword properties, the dot access doesn't work:
101101
user.likes birds = true
102102
```
103103

104-
That's because the dot requires the key to be a valid variable identifier. That is: no spaces and other limitations.
104+
JavaScript doesn't understand that. It thinks that we address `user.likes`, and then gives a syntax error when comes across unexpected `birds`.
105+
106+
The dot requires the key to be a valid variable identifier. That implies: contains no spaces, doesn't start with a digit and doesn't include special characters (`$` и `_` are allowed).
105107

106108
There's an alternative "square bracket notation" that works with any string:
107109

@@ -203,43 +205,6 @@ Square brackets are much more powerful than the dot notation. They allow any pro
203205

204206
So most of the time, when property names are known and simple, the dot is used. And if we need something more complex, then we switch to square brackets.
205207

206-
207-
208-
````smart header="Reserved words are allowed as property names"
209-
A variable cannot have a name equal to one of language-reserved words like "for", "let", "return" etc.
210-
211-
But for an object property, there's no such restriction. Any name is fine:
212-
213-
```js run
214-
let obj = {
215-
for: 1,
216-
let: 2,
217-
return: 3
218-
};
219-
220-
alert( obj.for + obj.let + obj.return ); // 6
221-
```
222-
223-
Basically, any name is allowed, but there's a special one: `"__proto__"` that gets special treatment for historical reasons. For instance, we can't set it to a non-object value:
224-
225-
```js run
226-
let obj = {};
227-
obj.__proto__ = 5;
228-
alert(obj.__proto__); // [object Object], didn't work as intended
229-
```
230-
231-
As we see from the code, the assignment to a primitive `5` is ignored.
232-
233-
That can become a source of bugs and even vulnerabilities if we intend to store arbitrary key-value pairs in an object, and allow a visitor to specify the keys.
234-
235-
In that case the visitor may choose `__proto__` as the key, and the assignment logic will be ruined (as shown above).
236-
237-
There is a way to make objects treat `__proto__` as a regular property, which we'll cover later, but first we need to know more about objects.
238-
239-
There's also another data structure [Map](info:map-set), that we'll learn in the chapter <info:map-set>, which supports arbitrary keys.
240-
````
241-
242-
243208
## Property value shorthand
244209

245210
In real code we often use existing variables as values for property names.
@@ -284,7 +249,63 @@ let user = {
284249
};
285250
```
286251

287-
## Existence check
252+
## Property names limitations
253+
254+
Property names (keys) must be either strings or symbols (a special type for identifiers, to be covered later).
255+
256+
Other types are automatically converted to strings.
257+
258+
For instance, a number `0` becomes a string `"0"` when used as a property key:
259+
260+
```js run
261+
let obj = {
262+
0: "test" // same as "0": "test"
263+
};
264+
265+
// both alerts access the same property (the number 0 is converted to string "0")
266+
alert( obj["0"] ); // test
267+
alert( obj[0] ); // test (same property)
268+
```
269+
270+
**Reserved words are allowed as property names.**
271+
272+
As we already know, a variable cannot have a name equal to one of language-reserved words like "for", "let", "return" etc.
273+
274+
But for an object property, there's no such restriction. Any name is fine:
275+
276+
```js run
277+
let obj = {
278+
for: 1,
279+
let: 2,
280+
return: 3
281+
};
282+
283+
alert( obj.for + obj.let + obj.return ); // 6
284+
```
285+
286+
We can use any string as a key, but there's a special property named `__proto__` that gets special treatment for historical reasons.
287+
288+
For instance, we can't set it to a non-object value:
289+
290+
```js run
291+
let obj = {};
292+
obj.__proto__ = 5; // assign a number
293+
alert(obj.__proto__); // [object Object] - the value is an object, didn't work as intended
294+
```
295+
296+
As we see from the code, the assignment to a primitive `5` is ignored.
297+
298+
The nature of `__proto__` will be revealed in detail later in the chapter [](info:prototype-inheritance).
299+
300+
As for now, it's important to know that such behavior of `__proto__` can become a source of bugs and even vulnerabilities if we intend to store user-provided keys in an object.
301+
302+
The problem is that a visitor may choose `__proto__` as the key, and the assignment logic will be ruined (as shown above).
303+
304+
Later we'll see workarounds for the problem:
305+
1. We'll see how to make an objects treat `__proto__` as a regular property in the chapter [](info:prototype-methods).
306+
2. There's also study another data structure [Map](info:map-set) in the chapter <info:map-set>, which supports arbitrary keys.
307+
308+
## Property existance test, "in" operator
288309

289310
A notable objects feature is that it's possible to access any property. There will be no error if the property doesn't exist! Accessing a non-existing property just returns `undefined`. It provides a very common way to test whether the property exists -- to get it and compare vs undefined:
290311

1-js/04-object-basics/03-symbol/article.md

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -178,22 +178,6 @@ alert( clone[id] ); // 123
178178

179179
There's no paradox here. That's by design. The idea is that when we clone an object or merge objects, we usually want *all* properties to be copied (including symbols like `id`).
180180

181-
````smart header="Property keys of other types are coerced to strings"
182-
We can only use strings or symbols as keys in objects. Other types are converted to strings.
183-
184-
For instance, a number `0` becomes a string `"0"` when used as a property key:
185-
186-
```js run
187-
let obj = {
188-
0: "test" // same as "0": "test"
189-
};
190-
191-
// both alerts access the same property (the number 0 is converted to string "0")
192-
alert( obj["0"] ); // test
193-
alert( obj[0] ); // test (same property)
194-
```
195-
````
196-
197181
## Global symbols
198182

199183
As we've seen, usually all symbols are different, even if they have the same name. But sometimes we want same-named symbols to be same entities. For instance, different parts of our application want to access symbol `"id"` meaning exactly the same property.

1-js/05-data-types/06-iterable/article.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ If an object isn't technically an array, but represents a collection (list, set)
1212

1313
We can easily grasp the concept of iterables by making one of our own.
1414

15-
For instance, we have an object, that is not an array, but looks suitable for `for..of`.
15+
For instance, we have an object that is not an array, but looks suitable for `for..of`.
1616

1717
Like a `range` object that represents an interval of numbers:
1818

@@ -294,7 +294,7 @@ Objects that can be used in `for..of` are called *iterable*.
294294

295295
- Technically, iterables must implement the method named `Symbol.iterator`.
296296
- The result of `obj[Symbol.iterator]` is called an *iterator*. It handles the further iteration process.
297-
- An iterator must have the method named `next()` that returns an object `{done: Boolean, value: any}`, here `done:true` denotes the iteration end, otherwise the `value` is the next value.
297+
- An iterator must have the method named `next()` that returns an object `{done: Boolean, value: any}`, here `done:true` denotes the end of the iteration process, otherwise the `value` is the next value.
298298
- The `Symbol.iterator` method is called automatically by `for..of`, but we also can do it directly.
299299
- Built-in iterables like strings or arrays, also implement `Symbol.iterator`.
300300
- String iterator knows about surrogate pairs.

1-js/05-data-types/08-weakmap-weakset/article.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ And here's another part of the code, maybe another file using it:
141141
let john = { name: "John" };
142142

143143
countUser(john); // count his visits
144-
countUser(john);
145144

146145
// later john leaves us
147146
john = null;

1-js/08-prototypes/01-prototype-inheritance/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ The prototype is a little bit "magical". When we want to read a property from `o
1616

1717
The property `[[Prototype]]` is internal and hidden, but there are many ways to set it.
1818

19-
One of them is to use `__proto__`, like this:
19+
One of them is to use the special name `__proto__`, like this:
2020

2121
```js run
2222
let animal = {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ fetch('/article/promise-chaining/user.json')
252252
});
253253
```
254254

255-
There is also a method `response.json()` that reads the remote data and parses it as JSON. In our case that's even more convenient, so let's switch to it.
255+
The `response` object returned from `fetch` also includes the method `response.json()` that reads the remote data and parses it as JSON. In our case that's even more convenient, so let's switch to it.
256256

257257
We'll also use arrow functions for brevity:
258258

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,11 @@ alert(str); // 0..9A..Za..z
314314

315315
A generator composition is a natural way to insert a flow of one generator into another. It doesn't use extra memory to store intermediate results.
316316

317-
## "yield" is a two-way road
317+
## "yield" is a two-way street
318318

319319
Until this moment, generators were similar to iterable objects, with a special syntax to generate values. But in fact they are much more powerful and flexible.
320320

321-
That's because `yield` is a two-way road: it not only returns the result outside, but also can pass the value inside the generator.
321+
That's because `yield` is a two-way street: it not only returns the result to the outside, but also can pass the value inside the generator.
322322

323323
To do so, we should call `generator.next(arg)`, with an argument. That argument becomes the result of `yield`.
324324

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,10 @@ async function* fetchCommits(repo) {
312312
}
313313
```
314314
315-
1. We use the browser [fetch](info:fetch) method to download from a remote URL. It allows to supply authorization and other headers if needed, here GitHub requires `User-Agent`.
316-
2. The fetch result is parsed as JSON, that's again a `fetch`-specific method.
317-
3. We should get the next page URL from the `Link` header of the response. It has a special format, so we use a regexp for that. The next page URL may look like `https://api.github.com/repositories/93253246/commits?page=2`, it's generated by GitHub itself.
318-
4. Then we yield all commits received, and when they finish -- the next `while(url)` iteration will trigger, making one more request.
315+
1. We use the browser [fetch](info:fetch) method to download from a remote URL. It allows us to supply authorization and other headers if needed -- here GitHub requires `User-Agent`.
316+
2. The fetch result is parsed as JSON. That's again a `fetch`-specific method.
317+
3. We should get the next page URL from the `Link` header of the response. It has a special format, so we use a regexp for that. The next page URL may look like `https://api.github.com/repositories/93253246/commits?page=2`. It's generated by GitHub itself.
318+
4. Then we yield all commits received, and when they finish, the next `while(url)` iteration will trigger, making one more request.
319319
320320
An example of use (shows commit authors in console):
321321
@@ -360,4 +360,4 @@ Syntax differences between async and regular generators:
360360
361361
In web-development we often meet streams of data, when it flows chunk-by-chunk. For instance, downloading or uploading a big file.
362362
363-
We can use async generators to process such data. It's also noteworthy that in some environments, such as browsers, there's also another API called Streams, that provides special interfaces to work with such streams, to transform the data and to pass it from one stream to another (e.g. download from one place and immediately send elsewhere).
363+
We can use async generators to process such data. It's also noteworthy that in some environments, like in browsers, there's also another API called Streams, that provides special interfaces to work with such streams, to transform the data and to pass it from one stream to another (e.g. download from one place and immediately send elsewhere).

1-js/13-modules/01-modules-intro/article.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ A module is just a file. One script is one module.
2424
Modules can load each other and use special directives `export` and `import` to interchange functionality, call functions of one module from another one:
2525

2626
- `export` keyword labels variables and functions that should be accessible from outside the current module.
27-
- `import` allows to import functionality from other modules.
27+
- `import` allows the import of functionality from other modules.
2828

2929
For instance, if we have a file `sayHi.js` exporting a function:
3030

@@ -45,7 +45,7 @@ alert(sayHi); // function...
4545
sayHi('John'); // Hello, John!
4646
```
4747

48-
The `import` directive loads the module by path `./sayHi.js` relative the current file and assigns exported function `sayHi` to the corresponding variable.
48+
The `import` directive loads the module by path `./sayHi.js` relative to the current file, and assigns exported function `sayHi` to the corresponding variable.
4949

5050
Let's run the example in-browser.
5151

@@ -85,7 +85,7 @@ Modules are expected to `export` what they want to be accessible from outside an
8585

8686
So we should import `user.js` into `hello.js` and get the required functionality from it instead of relying on global variables.
8787

88-
That's the correct variant:
88+
This is the correct variant:
8989

9090
[codetabs src="scopes-working" height="140" current="hello.js"]
9191

@@ -110,7 +110,7 @@ If we really need to make a window-level global variable, we can explicitly assi
110110

111111
If the same module is imported into multiple other places, its code is executed only the first time, then exports are given to all importers.
112112

113-
That has important consequences. Let's see that on examples.
113+
That has important consequences. Let's look at them using examples:
114114

115115
First, if executing a module code brings side-effects, like showing a message, then importing it multiple times will trigger it only once -- the first time:
116116

@@ -163,7 +163,7 @@ alert(admin.name); // Pete
163163

164164
So, let's reiterate -- the module is executed only once. Exports are generated, and then they are shared between importers, so if something changes the `admin` object, other modules will see that.
165165

166-
Such behavior allows to *configure* modules on first import. We can setup its properties once, and then in further imports it's ready.
166+
Such behavior allows us to *configure* modules on first import. We can setup its properties once, and then in further imports it's ready.
167167

168168
For instance, the `admin.js` module may provide certain functionality, but expect the credentials to come into the `admin` object from outside:
169169

@@ -268,11 +268,11 @@ Please note: the second script actually runs before the first! So we'll see `und
268268
269269
That's because modules are deferred, so we wait for the document to be processed. The regular script runs immediately, so we see its output first.
270270
271-
When using modules, we should be aware that HTML-page shows up as it loads, and JavaScript modules run after that, so the user may see the page before the JavaScript application is ready. Some functionality may not work yet. We should put "loading indicators", or otherwise ensure that the visitor won't be confused by that.
271+
When using modules, we should be aware that the HTML page shows up as it loads, and JavaScript modules run after that, so the user may see the page before the JavaScript application is ready. Some functionality may not work yet. We should put "loading indicators", or otherwise ensure that the visitor won't be confused by that.
272272
273273
### Async works on inline scripts
274274
275-
For non-module scripts, `async` attribute only works on external scripts. Async scripts run immediately when ready, independently of other scripts or the HTML document.
275+
For non-module scripts, the `async` attribute only works on external scripts. Async scripts run immediately when ready, independently of other scripts or the HTML document.
276276
277277
For module scripts, it works on inline scripts as well.
278278

0 commit comments

Comments
 (0)