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: types-grammar/ch1.md
+27-57Lines changed: 27 additions & 57 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,9 +9,11 @@ In Chapter 1 of the "Objects & Classes" book of this series, we confronted the c
9
9
10
10
Here, we'll look at the core value types of JS, specifically the non-object types called *primitives*.
11
11
12
-
## Built-in Values
12
+
## Value Types
13
13
14
-
JS provides seven built-in, primitive (non-object) value types:
14
+
JS doesn't apply types to variables or properties -- what I call, "container types" -- but rather, values themselves have types -- what I call, "value types".
15
+
16
+
The language provides seven built-in, primitive (non-object) value types:
JS doesn't apply types to variables or properties -- what I call, "container types" -- but rather, values themselves have types -- what I call, "value types".
25
-
26
-
These value-types define collections of one or more concrete values. Each value-type has a shared set of expected behaviors for all values of that type.
26
+
These value-types define collections of one or more concrete values, each with a set of shared behaviors for all values of that type.
27
27
28
28
### Type-Of
29
29
@@ -48,7 +48,7 @@ typeof greeting; // "string"
48
48
49
49
JS variables themselves don't have types. They hold any arbitrary value, which itself has a value-type.
50
50
51
-
###Empty Values
51
+
## Empty Values
52
52
53
53
The `null` and `undefined` types both typically represent an emptiness or absence of value.
However, each respective "empty" type has exactly one value, of the same name. So `null` is the only value in the `null` value-type, and `undefined` is the only value in the `undefined` value-type.
85
85
86
-
####Null'ish
86
+
### Null'ish
87
87
88
88
Semantically, `null` and `undefined` types both represent general emptiness, or absence of another affirmative, meaningful value.
89
89
@@ -164,7 +164,7 @@ The `?.(` operator seems like it is checking to see if `someFunc(..)` is a valid
164
164
| :--- |
165
165
| Because of that gotcha, I *strongly dislike* this operator form, and caution anyone against ever using it. I think it's a poorly conceived feature that does more harm (to JS itself, and to programs) than good. There's very few JS features I would go so far as to say, "never use it." But this is one of the truly *bad parts* of the language, in my opinion. |
166
166
167
-
#### Distinct'ish
167
+
### Distinct'ish
168
168
169
169
It's important to keep in mind that `null` and `undefined` *are* actually distinct types, and thus `null` can be noticeably different from `undefined`. You can, carefully, construct programs that mostly treat them as indistinguishable. But that requires care and discipline by the developer. From JS's perspective, they're more often distinct.
170
170
@@ -186,7 +186,7 @@ The `= ..` clause on a parameter is referred to as the "parameter default". It o
186
186
187
187
There's no *right* or *wrong* way to use `null` or `undefined` in a program. So the takeaway is: be careful when choosing one value or the other. And if you're using them interchangeably, be extra careful.
188
188
189
-
### Boolean Values
189
+
## Boolean Values
190
190
191
191
The `boolean` type contains two values: `false` and `true`.
192
192
@@ -214,7 +214,7 @@ while (!isComplete) {
214
214
215
215
The `!` operator negates/flips a boolean value to the other one: `false` becomes `true`, and `true` becomes `false`.
216
216
217
-
### String Values
217
+
## String Values
218
218
219
219
The `string` type contains any value which is a collection of one or more characters, delimited (surrounding on either side) by quote characters:
220
220
@@ -234,7 +234,7 @@ myName.length; // 4
234
234
235
235
This does not necessarily correspond to the number of visible characters present between the start and end delimiters (aka, the string literal). It can sometimes be a little confusing to keep straight the difference between a string literal and the underlying string value, so pay close attention.
236
236
237
-
#### JS Character Encodings
237
+
### JS Character Encodings
238
238
239
239
What type of character encoding does JS use for string characters?
240
240
@@ -250,7 +250,7 @@ This has implications on the length of strings, because a single visible charact
250
250
251
251
We'll revisit Unicode characters shortly.
252
252
253
-
#### Escape Sequences
253
+
### Escape Sequences
254
254
255
255
If `"` or `'` are used to delimit a string literal, the contents are only parsed for *character-escape sequences*: `\` followed by one or more characters that JS recognizes and parses with special meaning. Any other characters in a string that don't parse as escape-sequences (single-character or multi-character), are inserted as-is into the string value.
| What about four backslashes `\\\\` in a string literal? Well, that's just two `\\` escape sequences next to each other, so it results in two adjacent backslashes (`\\`) in the underlying string value. You might recognize there's an odd/even rule pattern at play. You should thus be able to deciper any odd (`\\\\\`, `\\\\\\\\\`, etc) or even (`\\\\\\`, `\\\\\\\\\\`, etc) number of backslashes in a string literal. |
287
287
288
-
#### Multi-Character Escapes
288
+
### Multi-Character Escapes
289
289
290
290
Multi-character escape sequences may be hexadecimal or Unicode sequences.
291
291
@@ -303,7 +303,7 @@ For any normal character that can be typed on a keyboard, such as `"a"`, it's us
@@ -338,7 +338,7 @@ All three representations of this same character are stored internally by JS ide
338
338
339
339
Even though JS doesn't care which way such a character is represented in your program, consider the readability differences carefully when authoring your code.
340
340
341
-
#### Line Continuation
341
+
### Line Continuation
342
342
343
343
The `\` followed by an actual new-line character (not just literal `n`) is a special case, and it creates what's called a line-continuation:
344
344
@@ -358,7 +358,7 @@ Because the end-of-line `\` turns the new-line character into a line continuatio
358
358
| :--- |
359
359
| This line-continuation feature is often referred to as "multi-line strings", but I think that's a confusing label. As you can see, the string value itself doesn't have multiple lines, it only was defined across multiple lines via the line continuations. A multi-line string would actually have multiple lines in the underlying value. |
360
360
361
-
#### Template Literals
361
+
### Template Literals
362
362
363
363
I mentioned earlier that strings can alternately be delimited with `` `..` `` back-ticks:
364
364
@@ -423,7 +423,7 @@ Moreover, there are a few places where `` `..` `` style strings are disallowed.
423
423
424
424
My take: use ```..``` delimited strings where allowed, but only when interpolation/multi-line is needed; and keep using `".."` or `'..'` delimited strings for everything else.
425
425
426
-
### Number Values
426
+
## Number Values
427
427
428
428
The `number` type contains any numeric value (whole number or decimal), such as `-42` or `3.1415926`. These values are represented by the JS engine as 64-bit, IEEE-754 double-precision binary floating-point values. [^IEEE754]
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
445
@@ -482,7 +482,7 @@ Number("512px"); // NaN
482
482
+"512px"; // NaN
483
483
```
484
484
485
-
#### IEEE-754 Bitwise Binary Representations
485
+
### IEEE-754 Bitwise Binary Representations
486
486
487
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.
488
488
@@ -525,7 +525,7 @@ Notice how the previous bit pattern and this one differ by quite a few bits in t
525
525
526
526
Now you understand a *bit more* about how IEEE-754 works!
527
527
528
-
##### Floating Point Imprecision
528
+
#### Floating Point Imprecision
529
529
530
530
One of the classic gotchas of any IEEE-754 number system in any programming language -- NOT UNIQUELY JS! -- is that not all operations and values can fit neatly into the IEEE-754 representations.
531
531
@@ -567,7 +567,7 @@ Pretty much all programmers need to be aware of IEEE-754 and make sure they are
567
567
| :--- |
568
568
| Shortly, we'll cover `Number.EPSILON`, which offers an approach to working around this floating point error situation when comparing numbers. |
569
569
570
-
#### Number Limits
570
+
### Number Limits
571
571
572
572
As might be evident now that you've seen how IEEE-754 works, the 52 bits of the number's base must be shared, representing both the whole number portion (if any) as well as the decimal portion (if any), of the intended `number` value. Essentially, the larger the whole number portion to be represented, the less bits are available for the decimal portion, and vice versa.
Most JS engines seem to have a minimum representable value around `5E-324` (about `2^-1074`). Depending on the engine and/or platform, a different value may be exposed. Be careful about any program logic that relies on such implementation-dependent values.
632
632
633
-
#### Safely Small
633
+
### Safely Small
634
634
635
635
There's another *very small* `number` value you may want to use:
636
636
@@ -660,7 +660,7 @@ Since JS cannot represent a difference between two values smaller than this `Num
660
660
| :--- |
661
661
| If your program needs to deal with smaller values, or more specifically, smaller differences between values, than `2^-52`, you should absolutely *not use* the `number` value-type. There are decimal-emulation libraries that can offer arbitrary (small or large) precision. Or pick a different language than JS. |
662
662
663
-
#### Safe Integer Limits
663
+
### Safe Integer Limits
664
664
665
665
Since `Number.MAX_VALUE` is an integer, you might assume that it's the largest integer in the language. But that's not really accurate.
666
666
@@ -686,7 +686,7 @@ Depending on how you interpret "smallest", you could either answer `0` or... `Nu
686
686
Number.MIN_SAFE_INTEGER; // -9007199254740991
687
687
```
688
688
689
-
#### Double Zeros
689
+
### Double Zeros
690
690
691
691
It may surprise you to learn that JS has two zeros: `0`, and `-0` (negative zero). But what on earth is a "negative zero"? A mathematician would surely balk at such a notion.
692
692
@@ -712,7 +712,7 @@ You may wonder why we'd ever need such a thing as `-0`. It can be useful when us
712
712
713
713
Without having a signed zero value, you couldn't tell which direction such an item was pointing at the moment it came to rest.
714
714
715
-
#### Invalid Number
715
+
### Invalid Number
716
716
717
717
Mathematical operations can sometimes produce an invalid result. For example:
718
718
@@ -772,7 +772,7 @@ If you're not properly checking for `NaN` in your programs where you do math or
772
772
| :--- |
773
773
| JS originally provided a global function called `isNaN(..)` for `NaN` checking, but it unfortunately has a long-standing coercion bug. `isNaN("Kyle")` returns `true`, even though the string value `"Kyle"` is most definitely *not* the `NaN` value. This is because the global `isNaN(..)` function forces any non-`number` argument to coerce to a `number` first, before checking for `NaN`. Coercing `"Kyle"` to a `number` produces `NaN`, so now the function sees a `NaN` and returns `true`! This buggy global `isNaN(..)` still exists in JS, but should never be used. When `NaN` checking, always use `Number.isNaN(..)`, `Object.is(..)`, etc. |
774
774
775
-
### BigInteger Values
775
+
## BigInteger Values
776
776
777
777
As the maximum safe integer in JS `number`s is `9007199254740991`, such a relatively low limit can present a problem if a JS program needs to do larger integer math, or even just hold values like 64-bit integer IDs (e.g., Twitter Tweet IDs).
778
778
@@ -838,7 +838,7 @@ Unlike `parseInt(..)`, if any character in the string is non-numeric (`0-9` digi
838
838
| :--- |
839
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. |
840
840
841
-
### Symbol Values
841
+
## Symbol Values
842
842
843
843
The `symbol` type contains special opaque values called "symbols". These values can only be created by the `Symbol(..)` function:
844
844
@@ -858,36 +858,6 @@ Symbols are guaranteed by the JS engine to be unique (only within the program it
858
858
859
859
// TODO
860
860
861
-
## Value Immutability
862
-
863
-
All primitive values are immutable, meaning nothing in a JS program can reach into the inside of the value and modify it in any way.
864
-
865
-
New values are created through operations, but these do not modify the original value.
866
-
867
-
```js
868
-
42+1; // 43
869
-
870
-
"Hello"+"!"; // "Hello!"
871
-
```
872
-
873
-
The values `43` and `"Hello!"` are new, distinct values from the `42` and `"Hello"` values, respectively.
874
-
875
-
// TODO
876
-
877
-
## Assignments Are Value Copies
878
-
879
-
Any assignment of a value from one variable/container to another is a *value-copy*.
880
-
881
-
```js
882
-
myAge =42;
883
-
884
-
yourAge = myAge; // assigned by value-copy
885
-
```
886
-
887
-
Here, the `myAge` and `yourAge` variables each have their own copy of the number value `42`. That means if we later re-assign `myAge` to `43` when I have a birthday, it doesn't affect the `42` that's still assigned to `yourAge`.
888
-
889
-
// TODO
890
-
891
861
[^UTFUCS]: "JavaScript’s internal character encoding: UCS-2 or UTF-16?"; Mathias Bynens; January 20 2012; https://mathiasbynens.be/notes/javascript-encoding ; Accessed July 2022
892
862
893
863
[^IEEE754]: "IEEE-754"; https://en.wikipedia.org/wiki/IEEE_754 ; Accessed July 2022
All primitive values are immutable, meaning nothing in a JS program can reach into the inside of the value and modify it in any way.
7
+
8
+
New values are created through operations, but these do not modify the original value.
9
+
10
+
```js
11
+
42+1; // 43
12
+
13
+
"Hello"+"!"; // "Hello!"
14
+
```
15
+
16
+
The values `43` and `"Hello!"` are new, distinct values from the `42` and `"Hello"` values, respectively.
17
+
18
+
// TODO
19
+
20
+
## Assignments Are Value Copies
21
+
22
+
Any assignment of a value from one variable/container to another is a *value-copy*.
23
+
24
+
```js
25
+
myAge =42;
26
+
27
+
yourAge = myAge; // assigned by value-copy
28
+
```
29
+
30
+
Here, the `myAge` and `yourAge` variables each have their own copy of the number value `42`. That means if we later re-assign `myAge` to `43` when I have a birthday, it doesn't affect the `42` that's still assigned to `yourAge`.
0 commit comments