To add new immutable datatypes that are identified up to their contents rather than by reference in the heap.
This allows us to add new integer types such as int64 and bignum without extending the set of typeof tags.
It also allows us to extend the behavior of the built-in operators to work on these new types.
Finally, it allows dealing with 64-bit values in marshalling and unmarshalling, like HTML5 File API and typed arrays.
Oh, and we could probably do IEE754r decimal, too.
let x = uint64(17); let y = uint64(17); console.log(x === y) // true console.log(typeof x) // "object" console.log(Object.isValue(x)) // true console.log(Object.isValue({})) // false
function factorial(n) { return n <= 1 ? bignum(1) : n * factorial(n - 1); } console.log(factorial(bignum(500))); // 122013682599111006870123878542304692625357434280319284219241 // 358838584537315388199760549644750220328186301361647714820358 // 416337872207817720048078520515932928547790757193933060377296 // 085908627042917454788242491272634430567017327076946106280231 // 045264421887878946575477714986349436778103764427403382736539 // 747138647787849543848959553753799042324106127132698432774571 // 554630997720278101456108118837370953101635632443298702956389 // 662891165897476957208792692887128178007026517450776841071962 // 439039432253642260523494585012991857150124870696156814162535 // 905669342381300885624924689156412677565448188650659384795177 // 536089400574523894033579847636394490531306232374906644504882 // 466507594673586207463792518420045936969298102226397195259719 // 094521782333175693458150855233282076282002340262690789834245 // 171200620771464097945611612762914595123722991334016955236385 // 094288559201872743379517301458635757082835578015873543276888 // 868012039988238470215146760544540766353598417443048012893831 // 389688163948746965881750450692636533817505547812864000000000 // 000000000000000000000000000000000000000000000000000000000000 // 0000000000000000000000000000000000000000000000000000000
===, to work with these new value types.typeof is unchanged=== is actually not any different from a constructor that keeps a memo-tableA predicate for detecting whether a given value is a non-reference value. (In pointy-headed semantics terminology, determining whether a given expressed value is also a stored value. See, there’s different kinds of “value” in the world, so you need different qualifiers to avoid confusion. End of nerdy semantics rant.)
Returns true for all primitives and for value objects, false for all reference objects.
Weak maps are intended to be keyed by objects that can become garbage. It doesn’t make sense to expose the “lifetime” of value objects, since their lifetimes should be completely hidden from programs. For example, a program may stack-allocate value objects sometimes, and they may garbage collect value objects and then recreate them later (for example, if they are recreated via eval of a literal).
So a weak map should reject the use of value objects as keys. (The Object.isValue predicate is a test for this distinction.)
We could allow user-defined value objects. But this opens the door to arbitrary operator overloading. I prefer to keep this proposal fixed. It’s forwards-compatible with future mechanisms for user-defined value objects.
We could define a new typeof type, to indicate that this is different from ordinary objects. But making a separate family of objects keeps this proposal maximally backwards-compatible.