Skip to content

Commit 028d718

Browse files
committed
Merge branch 'master' of github.com:javascript-tutorial/en.javascript.info into sync-28ed5a3f
2 parents f5a391a + 28ed5a3 commit 028d718

File tree

68 files changed

+607
-582
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+607
-582
lines changed

1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ describe("pow", function() {
44
assert.equal(pow(2, 3), 8);
55
});
66

7-
it("3 raised to power 3 is 27", function() {
8-
assert.equal(pow(3, 3), 27);
7+
it("3 raised to power 4 is 81", function() {
8+
assert.equal(pow(3, 4), 81);
99
});
1010

1111
});

1-js/05-data-types/01-primitives-methods/article.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Let's look at the key distinctions between primitives and objects.
77
A primitive
88

99
- Is a value of a primitive type.
10-
- There are 6 primitive types: `string`, `number`, `boolean`, `symbol`, `null` and `undefined`.
10+
- There are 7 primitive types: `string`, `number`, `bigint`, `boolean`, `symbol`, `null` and `undefined`.
1111

1212
An object
1313

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
function groupById(array) {
2+
return array.reduce((obj, value) => {
3+
obj[value.id] = value;
4+
return obj;
5+
}, {})
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
describe("groupById", function() {
2+
3+
it("creates an object grouped by id", function() {
4+
let users = [
5+
{id: 'john', name: "John Smith", age: 20},
6+
{id: 'ann', name: "Ann Smith", age: 24},
7+
{id: 'pete', name: "Pete Peterson", age: 31},
8+
];
9+
10+
assert.deepEqual(groupById(users), {
11+
john: {id: 'john', name: "John Smith", age: 20}
12+
ann: {id: 'ann', name: "Ann Smith", age: 24},
13+
pete: {id: 'pete', name: "Pete Peterson", age: 31},
14+
});
15+
});
16+
17+
it("works with an empty array", function() {
18+
assert.deepEqual(groupById(users), {});
19+
});
20+
});

1-js/05-data-types/05-array-methods/12-reduce-object/solution.md

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
importance: 4
2+
3+
---
4+
5+
# Create keyed object from array
6+
7+
Let's say we received an array of users in the form `{id:..., name:..., age... }`.
8+
9+
Create a function `groupById(arr)` that creates an object from it, with `id` as the key, and array items as values.
10+
11+
For example:
12+
13+
```js
14+
let users = [
15+
{id: 'john', name: "John Smith", age: 20},
16+
{id: 'ann', name: "Ann Smith", age: 24},
17+
{id: 'pete', name: "Pete Peterson", age: 31},
18+
];
19+
20+
let usersById = groupById(users);
21+
22+
/*
23+
// after the call we have:
24+
25+
usersById = {
26+
john: {id: 'john', name: "John Smith", age: 20}
27+
ann: {id: 'ann', name: "Ann Smith", age: 24},
28+
pete: {id: 'pete', name: "Pete Peterson", age: 31},
29+
}
30+
*/
31+
```
32+
33+
Such function is really handy when working with server data.
34+
35+
In this task we assume that `id` is unique. There may be no two array items with the same `id`.
36+
37+
Please use array `.reduce` method in the solution.

1-js/05-data-types/05-array-methods/article.md

+22-6
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ The order became `1, 15, 2`. Incorrect. But why?
384384

385385
**The items are sorted as strings by default.**
386386

387-
Literally, all elements are converted to strings for comparisons. For strings, lexicographic ordering is applied and indeed `"2" > "15"`.
387+
Literally, all elements are converted to strings for comparisons. For strings, lexicographic ordering is applied and indeed `"2" > "15"`.
388388

389389
To use our own sorting order, we need to supply a function as the argument of `arr.sort()`.
390390

@@ -431,7 +431,6 @@ By the way, if we ever want to know which elements are compared -- nothing preve
431431

432432
The algorithm may compare an element with multiple others in the process, but it tries to make as few comparisons as possible.
433433

434-
435434
````smart header="A comparison function may return any number"
436435
Actually, a comparison function is only required to return a positive number to say "greater" and a negative number to say "less".
437436
@@ -456,6 +455,22 @@ arr.sort( (a, b) => a - b );
456455
This works exactly the same as the longer version above.
457456
````
458457

458+
````smart header="Use `localeCompare` for strings"
459+
Remember [strings](info:string#correct-comparisons) comparison algorithm? It compares letters by their codes by default.
460+
461+
For many alphabets, it's better to use `str.localeCompare` method to correctly sort letters, such as `Ö`.
462+
463+
For example, let's sort a few countries in German:
464+
465+
```js run
466+
let countries = ['Österreich', 'Andorra', 'Vietnam'];
467+
468+
alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich (wrong)
469+
470+
alert( countries.sort( (a, b) => a.localeCompare(b) ) ); // Andorra,Österreich,Vietnam (correct!)
471+
```
472+
````
473+
459474
### reverse
460475
461476
The method [arr.reverse](mdn:js/Array/reverse) reverses the order of elements in `arr`.
@@ -530,7 +545,7 @@ The methods [arr.reduce](mdn:js/Array/reduce) and [arr.reduceRight](mdn:js/Array
530545
The syntax is:
531546

532547
```js
533-
let value = arr.reduce(function(previousValue, item, index, array) {
548+
let value = arr.reduce(function(accumulator, item, index, array) {
534549
// ...
535550
}, [initial]);
536551
```
@@ -539,14 +554,16 @@ The function is applied to all array elements one after another and "carries on"
539554

540555
Arguments:
541556

542-
- `previousValue` -- is the result of the previous function call, equals `initial` the first time (if `initial` is provided).
557+
- `accumulator` -- is the result of the previous function call, equals `initial` the first time (if `initial` is provided).
543558
- `item` -- is the current array item.
544559
- `index` -- is its position.
545560
- `array` -- is the array.
546561

547562
As function is applied, the result of the previous function call is passed to the next one as the first argument.
548563

549-
Sounds complicated, but it's not if you think about the first argument as the "accumulator" that stores the combined result of all previous execution. And at the end it becomes the result of `reduce`.
564+
So, the first argument is essentially the accumulator that stores the combined result of all previous executions. And at the end it becomes the result of `reduce`.
565+
566+
Sounds complicated?
550567

551568
The easiest way to grasp that is by example.
552569

@@ -611,7 +628,6 @@ let arr = [];
611628
arr.reduce((sum, current) => sum + current);
612629
```
613630

614-
615631
So it's advised to always specify the initial value.
616632

617633
The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same, but goes from right to left.

1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md renamed to 1-js/06-advanced-functions/02-rest-parameters-spread/article.md

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rest parameters and spread operator
1+
# Rest parameters and spread syntax
22

33
Many JavaScript built-in functions support an arbitrary number of arguments.
44

@@ -122,7 +122,7 @@ As we remember, arrow functions don't have their own `this`. Now we know they do
122122
````
123123
124124
125-
## Spread operator [#spread-operator]
125+
## Spread syntax [#spread-syntax]
126126
127127
We've just seen how to get an array from the list of parameters.
128128
@@ -148,7 +148,7 @@ alert( Math.max(arr) ); // NaN
148148
149149
And surely we can't manually list items in the code `Math.max(arr[0], arr[1], arr[2])`, because we may be unsure how many there are. As our script executes, there could be a lot, or there could be none. And that would get ugly.
150150
151-
*Spread operator* to the rescue! It looks similar to rest parameters, also using `...`, but does quite the opposite.
151+
*Spread syntax* to the rescue! It looks similar to rest parameters, also using `...`, but does quite the opposite.
152152
153153
When `...arr` is used in the function call, it "expands" an iterable object `arr` into the list of arguments.
154154
@@ -169,7 +169,7 @@ let arr2 = [8, 3, -8, 1];
169169
alert( Math.max(...arr1, ...arr2) ); // 8
170170
```
171171
172-
We can even combine the spread operator with normal values:
172+
We can even combine the spread syntax with normal values:
173173
174174
175175
```js run
@@ -179,7 +179,7 @@ let arr2 = [8, 3, -8, 1];
179179
alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
180180
```
181181
182-
Also, the spread operator can be used to merge arrays:
182+
Also, the spread syntax can be used to merge arrays:
183183
184184
```js run
185185
let arr = [3, 5, 1];
@@ -192,17 +192,17 @@ let merged = [0, ...arr, 2, ...arr2];
192192
alert(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2)
193193
```
194194
195-
In the examples above we used an array to demonstrate the spread operator, but any iterable will do.
195+
In the examples above we used an array to demonstrate the spread syntax, but any iterable will do.
196196
197-
For instance, here we use the spread operator to turn the string into array of characters:
197+
For instance, here we use the spread syntax to turn the string into array of characters:
198198
199199
```js run
200200
let str = "Hello";
201201
202202
alert( [...str] ); // H,e,l,l,o
203203
```
204204
205-
The spread operator internally uses iterators to gather elements, the same way as `for..of` does.
205+
The spread syntax internally uses iterators to gather elements, the same way as `for..of` does.
206206
207207
So, for a string, `for..of` returns characters and `...str` becomes `"H","e","l","l","o"`. The list of characters is passed to array initializer `[...str]`.
208208
@@ -220,24 +220,24 @@ The result is the same as `[...str]`.
220220
But there's a subtle difference between `Array.from(obj)` and `[...obj]`:
221221
222222
- `Array.from` operates on both array-likes and iterables.
223-
- The spread operator operates only on iterables.
223+
- The spread syntax works only with iterables.
224224
225225
So, for the task of turning something into an array, `Array.from` tends to be more universal.
226226
227227
228228
## Summary
229229
230-
When we see `"..."` in the code, it is either rest parameters or the spread operator.
230+
When we see `"..."` in the code, it is either rest parameters or the spread syntax.
231231
232232
There's an easy way to distinguish between them:
233233
234234
- When `...` is at the end of function parameters, it's "rest parameters" and gathers the rest of the list of arguments into an array.
235-
- When `...` occurs in a function call or alike, it's called a "spread operator" and expands an array into a list.
235+
- When `...` occurs in a function call or alike, it's called a "spread syntax" and expands an array into a list.
236236
237237
Use patterns:
238238
239239
- Rest parameters are used to create functions that accept any number of arguments.
240-
- The spread operator is used to pass an array to functions that normally require a list of many arguments.
240+
- The spread syntax is used to pass an array to functions that normally require a list of many arguments.
241241
242242
Together they help to travel between a list and an array of parameters with ease.
243243
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
The answer is: **Pete**.
2+
3+
A function gets outer variables as they are now, it uses the most recent values.
4+
5+
Old variable values are not saved anywhere. When a function wants a variable, it takes the current value from its own Lexical Environment or the outer one.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
importance: 5
2+
3+
---
4+
5+
# Does a function pickup latest changes?
6+
7+
The function sayHi uses an external variable name. When the function runs, which value is it going to use?
8+
9+
```js
10+
let name = "John";
11+
12+
function sayHi() {
13+
alert("Hi, " + name);
14+
}
15+
16+
name = "Pete";
17+
18+
sayHi(); // what will it show: "John" or "Pete"?
19+
```
20+
21+
Such situations are common both in browser and server-side development. A function may be scheduled to execute later than it is created, for instance after a user action or a network request.
22+
23+
So, the question is: does it pick up the latest changes?

1-js/06-advanced-functions/03-closure/lexenv-nested-work.svg renamed to 1-js/06-advanced-functions/03-closure/2-closure-variable-access/lexenv-nested-work.svg

+1-1
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
The answer is: **Pete**.
2+
3+
The `work()` function in the code below gets `name` from the place of its origin through the outer lexical environment reference:
4+
5+
![](lexenv-nested-work.svg)
6+
7+
So, the result is `"Pete"` here.
8+
9+
But if there were no `let name` in `makeWorker()`, then the search would go outside and take the global variable as we can see from the chain above. In that case the result would be `"John"`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
importance: 5
2+
3+
---
4+
5+
# Which variables are available?
6+
7+
The function `makeWorker` below makes another function and returns it. That new function can be called from somewhere else.
8+
9+
Will it have access to the outer variables from its creation place, or the invocation place, or both?
10+
11+
```js
12+
function makeWorker() {
13+
let name = "Pete";
14+
15+
return function() {
16+
alert(name);
17+
};
18+
}
19+
20+
let name = "John";
21+
22+
// create a function
23+
let work = makeWorker();
24+
25+
// call it
26+
work(); // what will it show?
27+
```
28+
29+
Which value it will show? "Pete" or "John"?
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
The result is: **error**.
2+
3+
Try running it:
4+
5+
```js run
6+
let x = 1;
7+
8+
function func() {
9+
*!*
10+
console.log(x); // ReferenceError: Cannot access 'x' before initialization
11+
*/!*
12+
let x = 2;
13+
}
14+
15+
func();
16+
```
17+
18+
In this example we can observe the peculiar difference between a "non-existing" and "unitialized" variable.
19+
20+
As you may have read in the article [](info:closure), a variable starts in the "uninitialized" state from the moment when the execution enters a code block (or a function). And it stays uninitalized until the corresponding `let` statement.
21+
22+
In other words, a variable technically exists, but can't be used before `let`.
23+
24+
The code above demonstrates it.
25+
26+
```js
27+
function func() {
28+
*!*
29+
// the local variable x is known to the engine from the beginning of the function,
30+
// but "unitialized" (unusable) until let ("dead zone")
31+
// hence the error
32+
*/!*
33+
34+
console.log(x); // ReferenceError: Cannot access 'vx before initialization
35+
36+
let x = 2;
37+
}
38+
```
39+
40+
This zone of temporary unusability of a variable (from the beginning of the code block till `let`) is sometimes called the "dead zone".
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
importance: 4
2+
3+
---
4+
5+
# Is variable visible?
6+
7+
What will be the result of this code?
8+
9+
```js
10+
let x = 1;
11+
12+
function func() {
13+
console.log(x); // ?
14+
15+
let x = 2;
16+
}
17+
18+
func();
19+
```
20+
21+
P.S. There's a pitfall in this task. The solution is not obvious.

0 commit comments

Comments
 (0)