Packing as much as possible into a single cons cell, or a JS value, was (and is) important, so bit masking to distinguish between integers, floats, strings, functions, objects, was an inevitable approach.
JavaScript tried to make things artificially "simpler" by implicit conversions. As usual, the lack of consistency only lead to more eventual complexity than a sound solution would have in the first place.
Is 2 between 1.9 and 2.1? What about between 1.9 and 2.1111111111111111111111111111111111111111?
What about over/underflow? Do you wrap, clamp, throw an exception? Do you round or set +-inf? Can you divide by zero? Can you divide an integer by a floating point number, and if so what would the result be?
What happens if, say, you multiply an 8-bit and 16-bit integer and the result (using twos complement) doesn't fit in 8 bits?
"Use IEEE-754 doubles for everything" answers all these questions. I think JavaScript is basically junk, but I find at least this aspect to be rather elegant (to the point that I suspect it came from somewhere else, haha).
I'm not so sure about that. There is an alternative implementation of Lua called LuaJIT, which uses a similar NaN-tagging trick, and it also happens to be incredibly fast. LuaJIT uses the 5.1 version of the language, with some backported 5.2 features for compatibility, but it will likely never backport 64-bit integers from 5.3.
It's resulted in something like the Python 2/3 split. Except it's even worse because Lua has relatively little penetration as a general purpose scripting language, but is quite popular as a language that can be embedded in a program to add scripting capabilities. This means it's up to the developer of said program which version of Lua they choose to embed, and from what I can tell, most developers choose speed over 64-bit integer support.
It's not ideal to presume such a thing when there are ways to find out the answer, either from the link in a sibling comment or by observing JavaScript code that uses the Google Maps API or similar mapping APIs. How would you represent a latitude or longitude with a 32-bit integer?
I don't mean to pick on you. I have made these same kinds of assumptions too many times and it always got me in trouble.
Here's a particularly embarrassing example. When I did my first election results map for Google, I needed a way to represent the outline of a state. I saw that the Maps API supported polygons, so I thought "that's great, I can use a polygon for each state!"
Until the map went live and someone asked me "What happened to the northern part of Michigan [which isn't connected to the rest of the state]? And where are the rest of the Hawaiian Islands?"
It turned out that a single polygon wasn't enough to represent the outline of a state. Who would have guessed?
Don't let this happen to you. :-)