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/05-data-types/05-array-methods/article.md
+22-6
Original file line number
Diff line number
Diff line change
@@ -384,7 +384,7 @@ The order became `1, 15, 2`. Incorrect. But why?
384
384
385
385
**The items are sorted as strings by default.**
386
386
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"`.
388
388
389
389
To use our own sorting order, we need to supply a function as the argument of `arr.sort()`.
390
390
@@ -431,7 +431,6 @@ By the way, if we ever want to know which elements are compared -- nothing preve
431
431
432
432
The algorithm may compare an element with multiple others in the process, but it tries to make as few comparisons as possible.
433
433
434
-
435
434
````smart header="A comparison function may return any number"
436
435
Actually, a comparison function is only required to return a positive number to say "greater" and a negative number to say "less".
437
436
@@ -456,6 +455,22 @@ arr.sort( (a, b) => a - b );
456
455
This works exactly the same as the longer version above.
457
456
````
458
457
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
+
459
474
### reverse
460
475
461
476
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
530
545
The syntax is:
531
546
532
547
```js
533
-
let value =arr.reduce(function(previousValue, item, index, array) {
548
+
let value =arr.reduce(function(accumulator, item, index, array) {
534
549
// ...
535
550
}, [initial]);
536
551
```
@@ -539,14 +554,16 @@ The function is applied to all array elements one after another and "carries on"
539
554
540
555
Arguments:
541
556
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).
543
558
-`item` -- is the current array item.
544
559
-`index` -- is its position.
545
560
-`array` -- is the array.
546
561
547
562
As function is applied, the result of the previous function call is passed to the next one as the first argument.
548
563
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?
550
567
551
568
The easiest way to grasp that is by example.
552
569
@@ -611,7 +628,6 @@ let arr = [];
611
628
arr.reduce((sum, current) => sum + current);
612
629
```
613
630
614
-
615
631
So it's advised to always specify the initial value.
616
632
617
633
The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same, but goes from right to left.
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/02-rest-parameters-spread/article.md
+12-12
Original file line number
Diff line number
Diff line change
@@ -1,4 +1,4 @@
1
-
# Rest parameters and spread operator
1
+
# Rest parameters and spread syntax
2
2
3
3
Many JavaScript built-in functions support an arbitrary number of arguments.
4
4
@@ -122,7 +122,7 @@ As we remember, arrow functions don't have their own `this`. Now we know they do
122
122
````
123
123
124
124
125
-
## Spread operator [#spread-operator]
125
+
## Spread syntax [#spread-syntax]
126
126
127
127
We've just seen how to get an array from the list of parameters.
128
128
@@ -148,7 +148,7 @@ alert( Math.max(arr) ); // NaN
148
148
149
149
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.
150
150
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.
152
152
153
153
When `...arr` is used in the function call, it "expands" an iterable object `arr` into the list of arguments.
154
154
@@ -169,7 +169,7 @@ let arr2 = [8, 3, -8, 1];
169
169
alert( Math.max(...arr1, ...arr2) ); // 8
170
170
```
171
171
172
-
We can even combine the spread operator with normal values:
172
+
We can even combine the spread syntax with normal values:
alert(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2)
193
193
```
194
194
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.
196
196
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:
198
198
199
199
```js run
200
200
let str = "Hello";
201
201
202
202
alert( [...str] ); // H,e,l,l,o
203
203
```
204
204
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.
206
206
207
207
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]`.
208
208
@@ -220,24 +220,24 @@ The result is the same as `[...str]`.
220
220
But there's a subtle difference between `Array.from(obj)` and `[...obj]`:
221
221
222
222
- `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.
224
224
225
225
So, for the task of turning something into an array, `Array.from` tends to be more universal.
226
226
227
227
228
228
## Summary
229
229
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.
231
231
232
232
There's an easy way to distinguish between them:
233
233
234
234
- 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.
236
236
237
237
Use patterns:
238
238
239
239
- 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.
241
241
242
242
Together they help to travel between a list and an array of parameters with ease.
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.
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
+
functionsayHi() {
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?
The `work()` function in the code below gets `name` from the place of its origin through the outer lexical environment reference:
4
+
5
+

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"`.
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
+
functionfunc() {
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".
0 commit comments