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/ch4.md
+41Lines changed: 41 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,6 +15,45 @@ The JS specification details a number of *abstract operations*[^AbstractOperatio
15
15
16
16
These operations *look* as if they're real functions that could be called, such as `ToString(..)` or `ToNumber(..)`. But by *abstract*, we mean they only exist conceptually by these names; they aren't functions we can *directly* invoke in our programs. Instead, we invoke them implicitly/indirectly depending on the statements/expressions in our programs.
17
17
18
+
### ToBoolean
19
+
20
+
Decision making (conditional branching) always requires a boolean `true` or `false` value. But it's extremely common to want to make these decisions based on non-boolean value conditions, such as whether a string is empty or has anything in it.
21
+
22
+
When non-boolean values are encountered in a context that requires a boolean -- such as the condition clause of an `if` statement or `for` loop -- the `ToBoolean(..)`[^ToBoolean] abstract operation is invoked to facilitate the coercion.
23
+
24
+
All values in JS are in one of two buckets: *truthy* or *falsy*. Truthy values coerce via the `ToBoolean()` operation to `true`, whereas falsy values coerce to `false`:
25
+
26
+
```
27
+
// ToBoolean() is abstract
28
+
29
+
ToBoolean(undefined); // false
30
+
ToBoolean(null); // false
31
+
ToBoolean(""); // false
32
+
ToBoolean(0); // false
33
+
ToBoolean(-0); // false
34
+
ToBoolean(0n); // false
35
+
ToBoolean(NaN); // false
36
+
```
37
+
38
+
Simple rule: *any other value* that's not in the above list is truthy and coerces via `ToBoolean()` to `true`:
39
+
40
+
```
41
+
ToBoolean("hello"); // true
42
+
ToBoolean(42); // true
43
+
ToBoolean([ 1, 2, 3 ]); // true
44
+
ToBoolean({ a: 1 }); // true
45
+
```
46
+
47
+
Even values like `" "` (string with only whitespace), `[]` (empty array), and `{}` (empty object), which may seem intuitively like they're more "false" than "true", nevertheless coerce to `true`.
48
+
49
+
| WARNING: |
50
+
| :--- |
51
+
| There *are* narrow, tricky exceptions to this truthy rule. For example, the web platform has deprecated the long-standing `document.all` collection/array feature, though it cannot be removed entirely -- that would break too many sites. Even where `document.all` is still defined, it behaves as a "falsy object" that coerces to `false`; that means legacy conditional checks like `if (document.all) { .. }` no longer pass. |
52
+
53
+
The `ToBoolean()` coercion operation is basically a lookup table rather than an algorithm of steps to use in coercions a non-boolean to a boolean. Thus, some developers assert that this isn't *really* coercion the way other abstract coercion operations are. I think that's bogus. `ToBoolean()` converts from non-boolean value-types to a boolean, and that's clear cut type coercion (even if it's a very simple lookup instead of an algorithm).
54
+
55
+
Keep in mind: these rules of boolean coercion only apply when `ToBoolean()` is actually invoked. There are constructs/idioms in the JS language that may appear to involve boolean coercion but which don't actually do so.
56
+
18
57
### ToPrimitive
19
58
20
59
Any value that's not already a primitive can be reduced to a primitive using the `ToPrimitive()` (specifically, `OrdinaryToPrimitive()`[^OrdinaryToPrimitive]) abstract operation. Generally, the `ToPrimitive()` is given a *hint* to tell it whether a `number` or `string` is preferred.
@@ -161,6 +200,8 @@ By virtue of `ToPrimitive(..,"number")` delegation, these objects all have their
161
200
162
201
[^AbstractOperations]: "7.1 Type Conversion", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-type-conversion ; Accessed August 2022
163
202
203
+
[^ToBoolean]: "7.1.2 ToBoolean(argument)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-toboolean ; Accessed August 2022
204
+
164
205
[^OrdinaryToPrimitive]: "7.1.1.1 OrdinaryToPrimitive(O,hint)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-ordinarytoprimitive ; Accessed August 2022
165
206
166
207
[^ToString]: "7.1.17 ToString(argument)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-tostring ; Accessed August 2022
0 commit comments