Skip to content

Commit a390941

Browse files
committed
types-grammar, ch1: discussion of nullish values and operations
1 parent da0a636 commit a390941

File tree

1 file changed

+82
-7
lines changed

1 file changed

+82
-7
lines changed

types-grammar/ch1.md

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ typeof 42n; // "bigint"
3939
typeof Symbol("42"); // "symbol"
4040
```
4141

42-
The `typeof` operator, when used against a variable, is reporting the value-type of the value in the variable:
42+
The `typeof` operator, when used against a variable instead of a value, is reporting the value-type of *the value in the variable*:
4343

4444
```js
4545
greeting = "Hello";
4646
typeof greeting; // "string"
4747
```
4848

49-
Again, JS variables themselves don't have types. They hold any arbitrary value, which itself has a value-type.
49+
JS variables themselves don't have types. They hold any arbitrary value, which itself has a value-type.
5050

5151
### Empty Values
5252

@@ -58,7 +58,7 @@ The `null` value-type has an unexpected `typeof` result. Instead of `"null"`, we
5858
typeof null; // "object"
5959
```
6060

61-
No, that doesn't mean that `null` is somehow a special kind of object. It's just a legacy of early days of JS, which cannot be changed because of how much code out in the wild it could break.
61+
No, that doesn't mean that `null` is somehow a special kind of object. It's just a legacy of early days of JS, which cannot be changed because of how much code out in the wild it would break.
6262

6363
The `undefined` type is reported both for explicit `undefined` values and any place where a seemingly missing value is encountered:
6464

@@ -79,15 +79,90 @@ typeof whatever[10]; // "undefined"
7979

8080
| NOTE: |
8181
| :--- |
82-
| The `typeof nonExistent` expression is referring to an undeclared variable `nonExisttent`. Normally, an undeclared variable reference might cause an exception (in strict mode), but the `typeof` operator is afforded the special ability to safely access even non-existent identifiers and calmly return `"undefined"` instead of throwing an exception. |
82+
| The `typeof nonExistent` expression is referring to an undeclared variable `nonExisttent`. Normally, accessing an undeclared variable reference would cause an exception, but the `typeof` operator is afforded the special ability to safely access even non-existent identifiers and calmly return `"undefined"` instead of throwing an exception. |
8383

84-
However, each respective 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.
84+
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.
8585

86-
// TODO
86+
#### Null'ish
87+
88+
Semantically, `null` and `undefined` types both represent emptiness, or absence of another affirmative, meaningful value.
89+
90+
| NOTE: |
91+
| :--- |
92+
| JS operations which behave the same whether `null` or `undefined` is encountered, are referred to as "null'ish" (or "nullish"). I guess "undefined'ish" would look/sound too weird! |
93+
94+
For a lot of JS, especially the code developers write, these two *nullish* values are interchangeable; the decision to intentionally use/assign `null` or `undefined` in any given scenario is situation dependent and left up to the developer.
95+
96+
JS provides a number of capabilities for helping treat the two nullish values as indistinguishable.
97+
98+
For example, the `==` (coercive-equality comparision) operator specifically treats `null` and `undefined` as coercively equal to each other, but to no other values in the language. As such, as `.. == null` check is safe to perform if you want to check if a value is specifically either `null` or `undefined`:
99+
100+
```js
101+
if (greeting == null) {
102+
// greeting is nullish/empty
103+
}
104+
```
105+
106+
Another (recent) addition to JS is the `??` (nullish-coalescing) operator:
107+
108+
```js
109+
who = myName ?? "User";
110+
111+
// equivalent to:
112+
who = (myName != null) ? myName : "User";
113+
```
114+
115+
As the ternary equivalent illustrates, `??` checks to see if `myName` is non-nullish, and if so, returns its value. Otherwise, it returns the other operand (here, `"User"`).
116+
117+
Along with `??`, JS also added the `?.` (nullish conditional-chaining) operator:
118+
119+
```js
120+
record = {
121+
shippingAddress: {
122+
street: "123 JS Lane",
123+
city: "Browserville",
124+
state: "XY"
125+
}
126+
};
127+
128+
console.log( record?.shippingAddress?.street );
129+
// 123 JS Lane
130+
131+
console.log( record?.billingAddress?.street );
132+
// undefined
133+
```
134+
135+
The `?.` operator checks the value immediately preceding (to the left) value, and if it's nullish, the operator stops and returns an `undefined` value. Otherwise, it performs the `.` property access against that value and continues with the expression.
136+
137+
Just to be clear: `record?.` is saying, "check `record` for nullish before `.` property access". Additionally, `billingAddress?.` is saying, "check `billingAddress` for nullish before `.` property access".
138+
139+
| WARNING: |
140+
| :--- |
141+
| Some JS developers believe that the newer `?.` is superior to `.`, and should thus almost always be used instead of `.`. I believe that's an unwise perspective. First of all, it's adding extra visual clutter, which should only be done if you're getting benefit from it. Secondly, you should be aware of, and planning for, the emptiness of some value, to justify using `?.`. If you always expect a non-nullish value to be present in some expression, using `?.` to access a property on it is not only unnecessary/wasteful, but also could potentially hide future bugs where your assumption of value-presence had failed but `?.` covered it up. As with most features in JS, use `.` where it's most appropriate, and use `?.` where it's most appropriate. Never substitute one when the other is more appropriate. |
142+
143+
#### Distint'ish
144+
145+
It's important to keep in mind that `null` and `undefined` *are* actually distinct types, and thus `null` is quite noticeably distinct 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 often distinct.
146+
147+
There are cases where `null` and `undefined` will trigger different behavior by the language, which is important to keep in mind. We won't cover all the cases exhaustively here, but here's on example:
148+
149+
```js
150+
function greet(msg = "Hello") {
151+
console.log(msg);
152+
}
153+
154+
greet(); // Hello
155+
greet(undefined); // Hello
156+
greet("Hi"); // Hi
157+
158+
greet(null); // null
159+
```
160+
161+
The `= ..` clause on a parameter is referred to as the "parameter default". It only kicks in and assigns its default value to the parameter if the argument in that position is missing, or is exactly the `undefined` value. If you pass `null`, that clause doesn't trigger, and `null` is thus assigned to the parameter.
87162
88163
### Boolean Values
89164
90-
The `boolean` type contains two values: `true` and `false`.
165+
The `boolean` type contains two values: `false` and `true`.
91166
92167
// TODO
93168

0 commit comments

Comments
 (0)