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
If a string value holds numeric-looking contents, you may need to convert from that string value to a `number`, for mathematical operation purposes.
445
+
446
+
However, it's very important to distinguish between parsing-conversion and coercive-conversion.
447
+
448
+
We can parse-convert with JS's built-in `parseInt(..)` or `parseFloat(..)` utilities:
449
+
450
+
```js
451
+
someNumericText ="123.456";
452
+
453
+
parseInt(someNumericText,10); // 123
454
+
parseFloat(someNumericText); // 123.456
455
+
456
+
parseInt("42",10) ===parseFloat("42"); // true
457
+
458
+
parseInt("512px"); // 512
459
+
```
460
+
461
+
Parsing is a character-by-character (left-to-right) operation, that pulls out numeric-looking characters from the string, and puts them into a `number` value. Parsing stops once it encounters a character that's non-numeric (e.g., not `-`, `.` or `0`-`9`). If parsing fails on the first character, both utilities return the special `NaN` value (see "Invalid Number" below).
462
+
463
+
When `parseInt(..)` encounters the `.`, it stops, leaving only the `123` in the result `number` value. `parseFloat(..)` by contrast accepts this character, and keeps right on parsing.
464
+
465
+
The `parseInt(..)` utility specifically, takes as a second argument the `radix`: the numeric base to assume for parsing the string characters into a `number`. `10` is for standard base-10 numbers, `8` is for octal, and `16` is hexadecimal. Any other `radix`, like `23`, assumes `0` - `9` followed by `a` - `z` (case insensitive) character ordination.
466
+
467
+
If `radix` is omitted, the behavior of `parseInt(..)` is rather nuanced and confusing, in that it attempts to make a best-guess based on what it sees in the first character. This leads to lots of subtle bugs, so never rely on the default auto-guessing; always specify an explicit radix (like `10` in the calls above).
468
+
469
+
`parseFloat(..)` always parses with a radix of `10`.
470
+
471
+
In contrast to parsing-conversion, coercive-conversion is an all-or-nothing sort of operation. Either the entire contents of the string are recognized as numeric (integer or floating-point), or the whole conversion fails (resulting in `NaN` -- again, see "Invalid Number" later in this chapter).
472
+
473
+
Coercive-conversion can be done explicitly with the `Number(..)` function (no `new` keyword) or with the unary `+` operator in front of the value:
474
+
475
+
```js
476
+
someNumericText ="123.456";
477
+
478
+
Number(someNumericText); // 123.456
479
+
+someNumericText; // 123.456
480
+
481
+
Number("512px"); // NaN
482
+
+"512px"; // NaN
483
+
```
484
+
442
485
#### IEEE-754 Bitwise Binary Representations
443
486
444
487
IEEE-754[^IEEE754] is a technical standard for binary representation of decimal numbers. It's widely used by most computer programming languages, including JS, Python, Ruby, etc.
@@ -671,9 +714,15 @@ Without having a signed zero value, you couldn't tell which direction such an it
671
714
672
715
#### Invalid Number
673
716
674
-
Mathematical operations can sometimes produce an invalid result. For example, if you try to divide a number by a string (`42/"Kyle"`), that's an invalid mathematical operation.
717
+
Mathematical operations can sometimes produce an invalid result. For example:
718
+
719
+
```js
720
+
42/"Kyle"; // NaN
721
+
```
722
+
723
+
It's probably obvious, but if you try to divide a number by a string, that's an invalid mathematical operation.
675
724
676
-
Another type of invalid numeric operation is trying to convert/coerce a non-numeric type of value to a `number`. We can do so with either the `Number(..)` function (no `new` keyword) or with the unary `+` operator in front of the value:
725
+
Another type of invalid numeric operation is trying to coercively-convert a non-numeric resembling value to a `number`. As discussed earlier, we can do so with either the `Number(..)` function or the unary `+` operator:
677
726
678
727
```js
679
728
myAge =Number("just a number");
@@ -683,7 +732,7 @@ myAge; // NaN
683
732
+undefined; // NaN
684
733
```
685
734
686
-
All such invalid operations (mathematical or numeric) produce the special `number` value called `NaN`.
735
+
All such invalid operations (mathematical or coercive/numeric) produce the special `number` value called `NaN`.
687
736
688
737
The historical root of "NaN" (including from the IEEE-754[^IEEE754] specification) is as an acronym for "Not a Number". Unfortunately, that meaning produces confusion, since `NaN` is *absolutely* a `number`.
As you can see, the `bigint` value-type is able to do precise arithmetic above the integer limit of the `number` value-type.
802
+
752
803
| WARNING: |
753
804
| :--- |
754
805
| Notice that the `+` operator required `.. +2n` instead of just `.. +2`? You cannot mix `number` and `bigint` value-types in the same expression. This restriction is annoying, but it protects your program from invalid mathematical operations that would give non-obvious unexpected results. |
755
806
756
-
As shown, the `bigint` value-type is able to do precise arithmetic above the integer limit of the `number` value-type.
807
+
A `bigint` value can also be created with the `BigInt(..)` function; for example, to convert a whole (integer) `number` value to a `bigint`:
757
808
758
-
// TODO
809
+
```js
810
+
myAge =42n;
811
+
812
+
inc =1;
813
+
814
+
myAge +=BigInt(inc);
815
+
816
+
myAge; // 43n
817
+
```
818
+
819
+
| WARNING: |
820
+
| :--- |
821
+
| Though it may seem counter-intuitive to some readers, `BigInt(..)` is *always* called without the `new` keyword. If `new` is used, an exception will be thrown. |
822
+
823
+
That's definitely one of the most common usages of the `BigInt(..)` function: to convert `number`s to `bigint`s, for mathematical operation purposes.
824
+
825
+
But it's not that uncommon to have large integer values represented as strings, especially if those values are coming to the JS environment from other locations, or via exchange formats, which themselves do not support `bigint`-style values.
826
+
827
+
As such, `BigInt(..)` is useful to parse those string values and convert them to `bigint`s:
828
+
829
+
```js
830
+
myBigInt =BigInt("12345678901234567890");
831
+
832
+
myBigInt; // 12345678901234567890n
833
+
```
834
+
835
+
Unlike `parseInt(..)`, if any character in the string is non-numeric (`0-9` digits or `-`), including `.` or even a trailing `n` suffix character, an exception will be thrown. In other words, `BigInt(..)` is all-or-nothing in its parsing/conversion.
836
+
837
+
| NOTE: |
838
+
| :--- |
839
+
| I think it's absurd that `BigInt(..)` won't accept the trailing `n` character while string parsing (and effectively ignore it). I lobbied vehemently for that in the TC39 process, but was ultimately denied. In my opinion, it's now a tiny little wart on JS, but a wart nonetheless. |
759
840
760
841
### Symbol Values
761
842
@@ -765,6 +846,10 @@ The `symbol` type contains special opaque values called "symbols". These values
765
846
secret =Symbol("my secret");
766
847
```
767
848
849
+
| WARNING: |
850
+
| :--- |
851
+
| Just as with `BigInt(..)`, the `Symbol(..)` function must be called without the `new` keyword. |
852
+
768
853
The `"my secret"` string passed into the `Symbol` is *not* the symbol value itself, even though it seems that way. It's an optional descriptive label, used only for debugging purposes for the benefit of the developer.
769
854
770
855
The underlying value returned from `Symbol(..)` is a special kind of value that resists the program/developer inspecting anything about its underlying representation. That's what I mean by "opaque".
0 commit comments