Skip to content

Commit 591e933

Browse files
committed
types-grammar, ch4: adding discussion of 'ToBoolean()' abstract operation
1 parent 8090b3e commit 591e933

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

types-grammar/ch4.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,45 @@ The JS specification details a number of *abstract operations*[^AbstractOperatio
1515

1616
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.
1717

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+
1857
### ToPrimitive
1958

2059
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
161200

162201
[^AbstractOperations]: "7.1 Type Conversion", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-type-conversion ; Accessed August 2022
163202

203+
[^ToBoolean]: "7.1.2 ToBoolean(argument)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-toboolean ; Accessed August 2022
204+
164205
[^OrdinaryToPrimitive]: "7.1.1.1 OrdinaryToPrimitive(O,hint)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-ordinarytoprimitive ; Accessed August 2022
165206

166207
[^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

Comments
 (0)