Skip to content

Commit bac68e8

Browse files
Merge pull request #183
main sync
2 parents 022aad3 + 65f48f0 commit bac68e8

File tree

18 files changed

+286
-335
lines changed

18 files changed

+286
-335
lines changed

1-js/05-data-types/01-primitives-methods/1-string-new-property/task.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ str.test = 5;
1515
alert(str.test);
1616
```
1717

18-
How do you think, will it work? What will be shown?
18+
What do you think, will it work? What will be shown?

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Objects are "heavier" than primitives. They require additional resources to supp
3939

4040
Here's the paradox faced by the creator of JavaScript:
4141

42-
- There are many things one would want to do with a primitive like a string or a number. It would be great to access them using methods.
42+
- There are many things one would want to do with a primitive, like a string or a number. It would be great to access them using methods.
4343
- Primitives must be as fast and lightweight as possible.
4444

4545
The solution looks a little bit awkward, but here it is:
@@ -104,9 +104,10 @@ if (zero) { // zero is true, because it's an object
104104
}
105105
```
106106

107-
On the other hand, using the same functions `String/Number/Boolean` without `new` is a totally sane and useful thing. They convert a value to the corresponding type: to a string, a number, or a boolean (primitive).
107+
On the other hand, using the same functions `String/Number/Boolean` without `new` is totally fine and useful thing. They convert a value to the corresponding type: to a string, a number, or a boolean (primitive).
108108

109109
For example, this is entirely valid:
110+
110111
```js
111112
let num = Number("123"); // convert a string to number
112113
```

1-js/05-data-types/02-number/2-why-rounded-down/solution.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ Note that `63.5` has no precision loss at all. That's because the decimal part `
2828

2929

3030
```js run
31-
alert( Math.round(6.35 * 10) / 10); // 6.35 -> 63.5 -> 64(rounded) -> 6.4
31+
alert( Math.round(6.35 * 10) / 10 ); // 6.35 -> 63.5 -> 64(rounded) -> 6.4
3232
```
3333

1-js/05-data-types/02-number/article.md

+59-21
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
In modern JavaScript, there are two types of numbers:
44

5-
1. Regular numbers in JavaScript are stored in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), also known as "double precision floating point numbers". These are numbers that we're using most of the time, and we'll talk about them in this chapter.
5+
1. Regular numbers in JavaScript are stored in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754), also known as "double precision floating point numbers". These are numbers that we're using most of the time, and we'll talk about them in this chapter.
66

7-
2. BigInt numbers, to represent integers of arbitrary length. They are sometimes needed, because a regular number can't safely exceed <code>2<sup>53</sup></code> or be less than <code>-2<sup>53</sup></code>. As bigints are used in few special areas, we devote them a special chapter <info:bigint>.
7+
2. BigInt numbers represent integers of arbitrary length. They are sometimes needed because a regular integer number can't safely exceed <code>(2<sup>53</sup>-1)</code> or be less than <code>-(2<sup>53</sup>-1)</code>, as we mentioned earlier in the chapter <info:types>. As bigints are used in few special areas, we devote them a special chapter <info:bigint>.
88

99
So here we'll talk about regular numbers. Let's expand our knowledge of them.
1010

@@ -22,7 +22,7 @@ We also can use underscore `_` as the separator:
2222
let billion = 1_000_000_000;
2323
```
2424

25-
Here the underscore `_` plays the role of the "syntactic sugar", it makes the number more readable. The JavaScript engine simply ignores `_` between digits, so it's exactly the same one billion as above.
25+
Here the underscore `_` plays the role of the "[syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar)", it makes the number more readable. The JavaScript engine simply ignores `_` between digits, so it's exactly the same one billion as above.
2626

2727
In real life though, we try to avoid writing long sequences of zeroes. We're too lazy for that. We'll try to write something like `"1bn"` for a billion or `"7.3bn"` for 7 billion 300 million. The same is true for most large numbers.
2828

@@ -47,10 +47,10 @@ Now let's write something very small. Say, 1 microsecond (one millionth of a sec
4747
let mсs = 0.000001;
4848
```
4949

50-
Just like before, using `"e"` can help. If we'd like to avoid writing the zeroes explicitly, we could say the same as:
50+
Just like before, using `"e"` can help. If we'd like to avoid writing the zeroes explicitly, we could write the same as:
5151

5252
```js
53-
let mcs = 1e-6; // six zeroes to the left from 1
53+
let mcs = 1e-6; // five zeroes to the left from 1
5454
```
5555

5656
If we count the zeroes in `0.000001`, there are 6 of them. So naturally it's `1e-6`.
@@ -63,6 +63,9 @@ In other words, a negative number after `"e"` means a division by 1 with the giv
6363

6464
// -6 divides by 1 with 6 zeroes
6565
1.23e-6 === 1.23 / 1000000; // 0.00000123
66+
67+
// an example with a bigger number
68+
1234e-2 === 1234 / 100; // 12.34, decimal point moves 2 times
6669
```
6770

6871
### Hex, binary and octal numbers
@@ -157,7 +160,7 @@ There are two ways to do so:
157160

158161
1. Multiply-and-divide.
159162

160-
For example, to round the number to the 2nd digit after the decimal, we can multiply the number by `100` (or a bigger power of 10), call the rounding function and then divide it back.
163+
For example, to round the number to the 2nd digit after the decimal, we can multiply the number by `100`, call the rounding function and then divide it back.
161164
```js run
162165
let num = 1.23456;
163166

@@ -178,28 +181,28 @@ There are two ways to do so:
178181
alert( num.toFixed(1) ); // "12.4"
179182
```
180183

181-
Please note that result of `toFixed` is a string. If the decimal part is shorter than required, zeroes are appended to the end:
184+
Please note that the result of `toFixed` is a string. If the decimal part is shorter than required, zeroes are appended to the end:
182185

183186
```js run
184187
let num = 12.34;
185188
alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits
186189
```
187190

188-
We can convert it to a number using the unary plus or a `Number()` call: `+num.toFixed(5)`.
191+
We can convert it to a number using the unary plus or a `Number()` call, e.g write `+num.toFixed(5)`.
189192

190193
## Imprecise calculations
191194

192-
Internally, a number is represented in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point (they are zero for integer numbers), and 1 bit is for the sign.
195+
Internally, a number is represented in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point, and 1 bit is for the sign.
193196

194-
If a number is too big, it would overflow the 64-bit storage, potentially giving an infinity:
197+
If a number is really huge, it may overflow the 64-bit storage and become a special numeric value `Infinity`:
195198

196199
```js run
197200
alert( 1e500 ); // Infinity
198201
```
199202

200203
What may be a little less obvious, but happens quite often, is the loss of precision.
201204

202-
Consider this (falsy!) test:
205+
Consider this (falsy!) equality test:
203206

204207
```js run
205208
alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!*
@@ -213,13 +216,13 @@ Strange! What is it then if not `0.3`?
213216
alert( 0.1 + 0.2 ); // 0.30000000000000004
214217
```
215218

216-
Ouch! There are more consequences than an incorrect comparison here. Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into their cart. The order total will be `$0.30000000000000004`. That would surprise anyone.
219+
Ouch! Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into their cart. The order total will be `$0.30000000000000004`. That would surprise anyone.
217220

218221
But why does this happen?
219222

220223
A number is stored in memory in its binary form, a sequence of bits - ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form.
221224

222-
In other words, what is `0.1`? It is one divided by ten `1/10`, one-tenth. In decimal numeral system such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`.
225+
What is `0.1`? It is one divided by ten `1/10`, one-tenth. In decimal numeral system such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`.
223226

224227
So, division by powers `10` is guaranteed to work well in the decimal system, but division by `3` is not. For the same reason, in the binary numeral system, the division by powers of `2` is guaranteed to work, but `1/10` becomes an endless binary fraction.
225228

@@ -246,7 +249,7 @@ Can we work around the problem? Sure, the most reliable method is to round the r
246249

247250
```js run
248251
let sum = 0.1 + 0.2;
249-
alert( sum.toFixed(2) ); // 0.30
252+
alert( sum.toFixed(2) ); // "0.30"
250253
```
251254

252255
Please note that `toFixed` always returns a string. It ensures that it has 2 digits after the decimal point. That's actually convenient if we have an e-shopping and need to show `$0.30`. For other cases, we can use the unary plus to coerce it into a number:
@@ -305,7 +308,7 @@ They belong to the type `number`, but are not "normal" numbers, so there are spe
305308
alert( isNaN("str") ); // true
306309
```
307310

308-
But do we need this function? Can't we just use the comparison `=== NaN`? Sorry, but the answer is no. The value `NaN` is unique in that it does not equal anything, including itself:
311+
But do we need this function? Can't we just use the comparison `=== NaN`? Unfortunately not. The value `NaN` is unique in that it does not equal anything, including itself:
309312

310313
```js run
311314
alert( NaN === NaN ); // false
@@ -331,16 +334,44 @@ alert( isFinite(num) );
331334

332335
Please note that an empty or a space-only string is treated as `0` in all numeric functions including `isFinite`.
333336

334-
```smart header="Compare with `Object.is`"
337+
````smart header="`Number.isNaN` and `Number.isFinite`"
338+
[Number.isNaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) and [Number.isFinite](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite) methods are the more "strict" versions of `isNaN` and `isFinite` functions. They do not autoconvert their argument into a number, but check if it belongs to the `number` type instead.
339+
340+
- `Number.isNaN(value)` returns `true` if the argument belongs to the `number` type and it is `NaN`. In any other case it returns `false`.
341+
342+
```js run
343+
alert( Number.isNaN(NaN) ); // true
344+
alert( Number.isNaN("str" / 2) ); // true
345+
346+
// Note the difference:
347+
alert( Number.isNaN("str") ); // false, because "str" belongs to the string type, not the number type
348+
alert( isNaN("str") ); // true, because isNaN converts string "str" into a number and gets NaN as a result of this conversion
349+
```
350+
351+
- `Number.isFinite(value)` returns `true` if the argument belongs to the `number` type and it is not `NaN/Infinity/-Infinity`. In any other case it returns `false`.
335352

336-
There is a special built-in method [`Object.is`](mdn:js/Object/is) that compares values like `===`, but is more reliable for two edge cases:
353+
```js run
354+
alert( Number.isFinite(123) ); // true
355+
alert( Number.isFinite(Infinity) ); // false
356+
alert( Number.isFinite(2 / 0) ); // false
357+
358+
// Note the difference:
359+
alert( Number.isFinite("123") ); // false, because "123" belongs to the string type, not the number type
360+
alert( isFinite("123") ); // true, because isFinite converts string "123" into a number 123
361+
```
362+
363+
In a way, `Number.isNaN` and `Number.isFinite` are simpler and more straightforward than `isNaN` and `isFinite` functions. In practice though, `isNaN` and `isFinite` are mostly used, as they're shorter to write.
364+
````
365+
366+
```smart header="Comparison with `Object.is`"
367+
There is a special built-in method `Object.is` that compares values like `===`, but is more reliable for two edge cases:
337368

338369
1. It works with `NaN`: `Object.is(NaN, NaN) === true`, that's a good thing.
339-
2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, technically that's true, because internally the number has a sign bit that may be different even if all other bits are zeroes.
370+
2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, technically that's correct, because internally the number has a sign bit that may be different even if all other bits are zeroes.
340371

341372
In all other cases, `Object.is(a, b)` is the same as `a === b`.
342373

343-
This way of comparison is often used in JavaScript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)).
374+
We mention `Object.is` here, because it's often used in JavaScript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)).
344375
```
345376

346377

@@ -400,8 +431,8 @@ A few examples:
400431
alert( Math.random() ); // ... (any random numbers)
401432
```
402433

403-
`Math.max(a, b, c...)` / `Math.min(a, b, c...)`
404-
: Returns the greatest/smallest from the arbitrary number of arguments.
434+
`Math.max(a, b, c...)` and `Math.min(a, b, c...)`
435+
: Returns the greatest and smallest from the arbitrary number of arguments.
405436

406437
```js run
407438
alert( Math.max(3, 5, -10, 0, 1) ); // 5
@@ -430,6 +461,13 @@ For different numeral systems:
430461
- `parseInt(str, base)` parses the string `str` into an integer in numeral system with given `base`, `2 ≤ base ≤ 36`.
431462
- `num.toString(base)` converts a number to a string in the numeral system with the given `base`.
432463

464+
For regular number tests:
465+
466+
- `isNaN(value)` converts its argument to a number and then tests it for being `NaN`
467+
- `Number.isNaN(value)` checks whether its argument belongs to the `number` type, and if so, tests it for being `NaN`
468+
- `isFinite(value)` converts its argument to a number and then tests it for not being `NaN/Infinity/-Infinity`
469+
- `Number.isFinite(value)` checks whether its argument belongs to the `number` type, and if so, tests it for not being `NaN/Infinity/-Infinity`
470+
433471
For converting values like `12pt` and `100px` to a number:
434472

435473
- Use `parseInt/parseFloat` for the "soft" conversion, which reads a number from a string and then returns the value they could read before the error.

1-js/05-data-types/03-string/1-ucfirst/solution.md

+1-7
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@ let newStr = str[0].toUpperCase() + str.slice(1);
88

99
There's a small problem though. If `str` is empty, then `str[0]` is `undefined`, and as `undefined` doesn't have the `toUpperCase()` method, we'll get an error.
1010

11-
There are two variants here:
12-
13-
1. Use `str.charAt(0)`, as it always returns a string (maybe empty).
14-
2. Add a test for an empty string.
15-
16-
Here's the 2nd variant:
11+
The easiest way out is to add a test for an empty string, like this:
1712

1813
```js run demo
1914
function ucFirst(str) {
@@ -24,4 +19,3 @@ function ucFirst(str) {
2419

2520
alert( ucFirst("john") ); // John
2621
```
27-

0 commit comments

Comments
 (0)