That's because javascript numbers are 64 bit floats.
Floating point numbers have 2 parts - the fractional part which defines the "value" of the number and the exponent part which defines how far to the left or right of the decimal point the number should be shifted.
To illustrate how this work I'll be using an imaginary floating point number format that is decimal based instead of binary:
Let's define our imaginary format as 8 character floats - that is the number must be stored within 8 characters. Lets partition our format to have 6 characters as the fractional part and 2 characters as the exponent:
_ _ _ _ _ _ _ _
|_ _|_ _ _ _ _ _| <--- 8 char float
exponent fractional
For ease of discussion, let's invent a syntax to describe the format:
exponent,fractional
So for example, the number 128
can be stored as 0,128
and PI can be stored as -5,314159
(the decimal point shifted to the left by 5 places).
The PI case above is how programmers first encounter floating point numbers - they need to work with fractional numbers instead of simple integers. But the floating point format also has another feature - it can store numbers bigger than the space allocated for the fractional part!
For example, what if we want to store the number 987654321 in our imaginary 8char floating point format? It's more than 6 characters! Well, we'd do it like this: 2,9876543
. That is, we store the most significant digits and shift the decimal point 2 spaces to the right.
If we try to read that number, what well get is 987654300. We've lost the least significant digits! Hmm.. sounds familiar.
In the case of javascript, the format is IEEE 754 64bit binary floating point. It has 52 bits allocated for the fractional part (53 if you include the sign bit). Which means that for numbers of up to 52 bits it behaves just like an integer. Any larger and it will begin sacrificing the least significant bits (not digits, bits, so the rounding may appear odd to us humans).
See this wikipedia article for more details on how 64bit floats work: http://en.wikipedia.org/wiki/Double_precision_floating-point_format