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/01-primitives-methods/article.md
+3-2
Original file line number
Diff line number
Diff line change
@@ -39,7 +39,7 @@ Objects are "heavier" than primitives. They require additional resources to supp
39
39
40
40
Here's the paradox faced by the creator of JavaScript:
41
41
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.
43
43
- Primitives must be as fast and lightweight as possible.
44
44
45
45
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
104
104
}
105
105
```
106
106
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).
108
108
109
109
For example, this is entirely valid:
110
+
110
111
```js
111
112
let num =Number("123"); // convert a string to number
Copy file name to clipboardexpand all lines: 1-js/05-data-types/02-number/article.md
+59-21
Original file line number
Diff line number
Diff line change
@@ -2,9 +2,9 @@
2
2
3
3
In modern JavaScript, there are two types of numbers:
4
4
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.
6
6
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 numbersrepresent 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>.
8
8
9
9
So here we'll talk about regular numbers. Let's expand our knowledge of them.
10
10
@@ -22,7 +22,7 @@ We also can use underscore `_` as the separator:
22
22
let billion =1_000_000_000;
23
23
```
24
24
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.
26
26
27
27
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.
28
28
@@ -47,10 +47,10 @@ Now let's write something very small. Say, 1 microsecond (one millionth of a sec
47
47
let mсs =0.000001;
48
48
```
49
49
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:
51
51
52
52
```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
54
54
```
55
55
56
56
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
63
63
64
64
// -6 divides by 1 with 6 zeroes
65
65
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
66
69
```
67
70
68
71
### Hex, binary and octal numbers
@@ -157,7 +160,7 @@ There are two ways to do so:
157
160
158
161
1. Multiply-and-divide.
159
162
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 of10), 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.
161
164
```js run
162
165
let num = 1.23456;
163
166
@@ -178,28 +181,28 @@ There are two ways to do so:
178
181
alert( num.toFixed(1) ); // "12.4"
179
182
```
180
183
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:
182
185
183
186
```js run
184
187
let num = 12.34;
185
188
alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits
186
189
```
187
190
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)`.
189
192
190
193
## Imprecise calculations
191
194
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.
193
196
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`:
195
198
196
199
```js run
197
200
alert( 1e500 ); // Infinity
198
201
```
199
202
200
203
What may be a little less obvious, but happens quite often, is the loss of precision.
201
204
202
-
Consider this (falsy!) test:
205
+
Consider this (falsy!) equality test:
203
206
204
207
```js run
205
208
alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!*
@@ -213,13 +216,13 @@ Strange! What is it then if not `0.3`?
213
216
alert( 0.1 + 0.2 ); // 0.30000000000000004
214
217
```
215
218
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.
217
220
218
221
But why does this happen?
219
222
220
223
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.
221
224
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)`.
223
226
224
227
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.
225
228
@@ -246,7 +249,7 @@ Can we work around the problem? Sure, the most reliable method is to round the r
246
249
247
250
```js run
248
251
let sum = 0.1 + 0.2;
249
-
alert( sum.toFixed(2) ); // 0.30
252
+
alert( sum.toFixed(2) ); //"0.30"
250
253
```
251
254
252
255
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
305
308
alert( isNaN("str") ); // true
306
309
```
307
310
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:
309
312
310
313
```js run
311
314
alert( NaN === NaN ); // false
@@ -331,16 +334,44 @@ alert( isFinite(num) );
331
334
332
335
Please note that an empty or a space-only string is treated as `0` in all numeric functions including `isFinite`.
333
336
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`.
335
352
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:
337
368
338
369
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.
340
371
341
372
In all other cases, `Object.is(a, b)` is the same as `a === b`.
342
373
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)).
344
375
```
345
376
346
377
@@ -400,8 +431,8 @@ A few examples:
400
431
alert( Math.random() ); // ... (any random numbers)
401
432
```
402
433
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.
405
436
406
437
```js run
407
438
alert( Math.max(3, 5, -10, 0, 1) ); // 5
@@ -430,6 +461,13 @@ For different numeral systems:
430
461
- `parseInt(str, base)` parses the string `str` into an integer in numeral system with given `base`, `2 ≤ base ≤ 36`.
431
462
- `num.toString(base)` converts a number to a string in the numeral system with the given `base`.
432
463
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
+
433
471
For converting values like `12pt` and `100px` to a number:
434
472
435
473
- 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.
Copy file name to clipboardexpand all lines: 1-js/05-data-types/03-string/1-ucfirst/solution.md
+1-7
Original file line number
Diff line number
Diff line change
@@ -8,12 +8,7 @@ let newStr = str[0].toUpperCase() + str.slice(1);
8
8
9
9
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.
10
10
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:
0 commit comments