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
+9-1Lines changed: 9 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -694,6 +694,10 @@ I'm not going to cover it exhaustively, but I think a brief primer on how number
694
694
695
695
In 64-bit IEEE-754 -- so called "double-precision", because originally IEEE-754 used to be 32-bit, and now it's double that! -- the 64 bits are divided into three sections: 52 bits for the number's base value (aka, "fraction", "mantissa", or "significand"), 11 bits for the exponent to raise `2` to before multiplying, and 1 bit for the sign of the ultimate value.
696
696
697
+
| NOTE: |
698
+
| :--- |
699
+
| Since only 52 of the 64 bits are actually used to represent the base value, `number` doesn't actually have `2^64` values in it. According to the specification for the `number` type[^NumberType], the number of values is precisely `2^64-2^53+3`, or about 18 quintillion, split about evenly between positive and negative numbers. |
700
+
697
701
These bits are arranged left-to-right, as so (S = Sign Bit, E = Exponent Bit, M = Mantissa Bit):
698
702
699
703
```js
@@ -881,7 +885,9 @@ myAge; // NaN
881
885
882
886
All such invalid operations (mathematical or coercive/numeric) produce the special `number` value called `NaN`.
883
887
884
-
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`.
888
+
The historical root of "NaN" (from the IEEE-754[^IEEE754] specification) is as an acronym for "Not a Number". Technically, there are about 9 quadrillion values in the 64-bit IEEE-754 number space designated as "NaN", but JS treats all of them indistinguishably as the single `NaN` value.
889
+
890
+
Unfortunately, that *not a number* meaning produces confusion, since `NaN` is *absolutely* a `number`.
885
891
886
892
| TIP: |
887
893
| :--- |
@@ -1111,3 +1117,5 @@ Before we move on to discussing JS's built-in object value type, we want to take
1111
1117
[^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
1112
1118
1113
1119
[^IEEE754]: "IEEE-754"; https://en.wikipedia.org/wiki/IEEE_754 ; Accessed July 2022
1120
+
1121
+
[^NumberType]: "6.1.6.1 The Number Type", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-ecmascript-language-types-number-type ; Accessed August 2022
Copy file name to clipboardExpand all lines: types-grammar/ch2.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -441,7 +441,7 @@ The `<=` (less-than-or-equal) and `>=` (greater-than-or-equal) operators are eff
441
441
442
442
| NOTE: |
443
443
| :--- |
444
-
| Here's an interesting bit of specification nuance: JS doesn't actually define the `>` and `>=` relational comparisons independently. Instead, it defines them as the negation of their complement counterparts. So `x > y` is treated by JS as `!(x <= y)`, and `x >= y` is treated by JS as `!(x < y)`. So JS only needs to specify how `<`, `<=`, and `!` work, and thus gets `>` and `>=` for free! |
444
+
| Here's an interesting bit of specification nuance: JS doesn't actually define the underlying greater-than (for `>`) or greater-than-or-equal (for `>=`) operations. Instead, it defines them by reversing the arguments to their *less-than*complement counterparts. So `x > y` is treated by JS essentially as `y <= x`, and `x >= y` is treated by JS essentially as `y < x`. So JS only needs to specify how `<`and `==` work, and thus gets `>` and `>=` for free! |
Copy file name to clipboardExpand all lines: types-grammar/ch4.md
+67-2Lines changed: 67 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -270,7 +270,7 @@ Different from `SameValue()` and its variations, the specification also defines
270
270
271
271
The `IsStrictlyEqual()` operation immediately returns `false` if the value-types being compared are different.
272
272
273
-
If the value-types are the same, `IsStrictlyEqual()` delegates to sub-operations for comparing `number` or `bigint` values. You might logically expect these delegated sub-operations to be the aforementioned numeric-specialized `SameValue()` / `SameValueZero()` operations. However, `IsStrictlyEqual()` instead delegates to `Number:equal()`[^NumberEqual] or `BigInt:equal()`[^BigIntEqual].
273
+
If the value-types are the same, `IsStrictlyEqual()` delegates to sub-operations for comparing `number` or `bigint` values. [^NumericAbstractOps]You might logically expect these delegated sub-operations to be the aforementioned numeric-specialized `SameValue()` / `SameValueZero()` operations. However, `IsStrictlyEqual()` instead delegates to `Number:equal()`[^NumberEqual] or `BigInt:equal()`[^BigIntEqual].
274
274
275
275
The difference between `Number:SameValue()` and `Number:equal()` is that the latter defines corner cases for `0` vs `-0` comparison:
276
276
@@ -319,7 +319,66 @@ Moreover, if/once the types are the same, both operations are identical -- `IsLo
319
319
320
320
### Relational Comparison
321
321
322
-
// TODO
322
+
When values are compared relationally -- that is, is one value "less than" another? -- there's one specific abstract operation that is invoked: `IsLessThan()`. [^LessThan]
323
+
324
+
```
325
+
// IsLessThan() is abstract
326
+
327
+
IsLessThan(1,2, /*LeftFirst=*/ true ); // true
328
+
```
329
+
330
+
There is no `IsGreaterThan()` operation; instead, the first two arguments to `IsLessThan()` can be reversed to accomplish a "greater than" comparison. To preserve left-to-right evaluation semantics (in the case of nuanced side-effects), `isLessThan()` also takes a third argument (`LeftFirst`); if `false`, this indicates a comparison was reversed and the second parameter should be evaluated before the first.
331
+
332
+
```
333
+
IsLessThan(1,2, /*LeftFirst=*/ true ); // true
334
+
335
+
// equivalent of a fictional "IsGreaterThan()"
336
+
IsLessThan(2,1, /*LeftFirst=*/ false ); // false
337
+
```
338
+
339
+
Similar to `IsLooselyEqual()`, the `IsLessThan()` operation is *coercive*, meaning that it first ensures that the value-types of its two values match, and prefers numeric comparisons. There is no `IsStrictLessThan()` for non-coercive relational comparison.
340
+
341
+
As an example of coercive relational comparison, if the type of one value is `string` and the type of the other is `bigint`, the `string` is coerced to a `bigint` with the aforementioned `StringToBigInt()` operation. Once the types are the same, `IsLessThan()` proceeds as described in the following sections.
342
+
343
+
#### String Comparison
344
+
345
+
When both value are type `string`, `IsLessThan()` checks to see if the lefthand value is a prefix (the first *n* characters[^StringPrefix]) of the righthand; if so, `true` is returned.
346
+
347
+
If neither string is a prefix of the other, the first character position (start-to-end direction, not left-to-right) that's different between the two strings, is compared for their respective code-unit (numeric) values; the result is then returned.
[^AbstractOperations]: "7.1 Type Conversion", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-type-conversion ; Accessed August 2022
325
384
@@ -347,6 +406,12 @@ Moreover, if/once the types are the same, both operations are identical -- `IsLo
347
406
348
407
[^LooseEquality]: "7.2.15 IsLooselyEqual(x,y)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-islooselyequal ; Accessed August 2022
349
408
409
+
[^NumericAbstractOps]: "6.1.6 Numeric Types", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-numeric-types ; Accessed August 2022
410
+
350
411
[^NumberEqual]: "6.1.6.1.13 Number:equal(x,y)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-numeric-types-number-equal ; Accessed August 2022
351
412
352
413
[^BigIntEqual]: "6.1.6.2.13 BigInt:equal(x,y)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-numeric-types-bigint-equal ; Accessed August 2022
414
+
415
+
[^LessThan]: "7.2.14 IsLessThan(x,y,LeftFirst)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-islessthan ; Accessed August 2022
416
+
417
+
[^StringPrefix]: "7.2.9 IsStringPrefix(p,q)", ECMAScript 2022 Language Specification; https://262.ecma-international.org/13.0/#sec-isstringprefix ; Accessed August 2022
0 commit comments