Number

Importantly, for your program to properly work, it must accurately handle numbers. ES6 adds some additional properties and functions to assist with common numeric operations.

Two additions to Number are just references to the preexisting globals: Number.parseInt(..) and Number.parseFloat(..).

Static Properties

ES6 adds some helpful numeric constants as static properties:

  • Number.EPSILON - The minimum value between any two numbers: 2^-52 (see Chapter 2 of the Types & Grammar title of this series regarding using this value as a tolerance for imprecision in floating-point arithmetic)
  • Number.MAX_SAFE_INTEGER - The highest integer that can “safely” be represented unambiguously in a JS number value: 2^53 - 1
  • Number.MIN_SAFE_INTEGER - The lowest integer that can “safely” be represented unambiguously in a JS number value: -(2^53 - 1) or (-2)^53 + 1.

Note: See Chapter 2 of the Types & Grammar title of this series for more information about “safe” integers.

Number.isNaN(..) Static Function

The standard global isNaN(..) utility has been broken since its inception, in that it returns true for things that are not numbers, not just for the actual NaN value, because it coerces the argument to a number type (which can falsely result in a NaN). ES6 adds a fixed utility Number.isNaN(..) that works as it should:

  1. var a = NaN, b = "NaN", c = 42;
  2. isNaN( a ); // true
  3. isNaN( b ); // true -- oops!
  4. isNaN( c ); // false
  5. Number.isNaN( a ); // true
  6. Number.isNaN( b ); // false -- fixed!
  7. Number.isNaN( c ); // false

Number.isFinite(..) Static Function

There’s a temptation to look at a function name like isFinite(..) and assume it’s simply “not infinite”. That’s not quite correct, though. There’s more nuance to this new ES6 utility. Consider:

  1. var a = NaN, b = Infinity, c = 42;
  2. Number.isFinite( a ); // false
  3. Number.isFinite( b ); // false
  4. Number.isFinite( c ); // true

The standard global isFinite(..) coerces its argument, but Number.isFinite(..) omits the coercive behavior:

  1. var a = "42";
  2. isFinite( a ); // true
  3. Number.isFinite( a ); // false

You may still prefer the coercion, in which case using the global isFinite(..) is a valid choice. Alternatively, and perhaps more sensibly, you can use Number.isFinite(+x), which explicitly coerces x to a number before passing it in (see Chapter 4 of the Types & Grammar title of this series).

JavaScript number values are always floating point (IEEE-754). So the notion of determining if a number is an “integer” is not about checking its type, because JS makes no such distinction.

Instead, you need to check if there’s any non-zero decimal portion of the value. The easiest way to do that has commonly been:

  1. x === Math.floor( x );

ES6 adds a Number.isInteger(..) helper utility that potentially can determine this quality slightly more efficiently:

  1. Number.isInteger( 4 ); // true
  2. Number.isInteger( 4.2 ); // false

Note: In JavaScript, there’s no difference between 4, 4., 4.0, or 4.0000. All of these would be considered an “integer”, and would thus yield true from Number.isInteger(..).

In addition, Number.isInteger(..) filters out some clearly not-integer values that x === Math.floor(x) could potentially mix up:

  1. Number.isInteger( NaN ); // false
  2. Number.isInteger( Infinity ); // false

Working with “integers” is sometimes an important bit of information, as it can simplify certain kinds of algorithms. JS code by itself will not run faster just from filtering for only integers, but there are optimization techniques the engine can take (e.g., asm.js) when only integers are being used.

Because of Number.isInteger(..)‘s handling of NaN and Infinity values, defining a isFloat(..) utility would not be just as simple as !Number.isInteger(..). You’d need to do something like:

  1. function isFloat(x) {
  2. return Number.isFinite( x ) && !Number.isInteger( x );
  3. }
  4. isFloat( 4.2 ); // true
  5. isFloat( 4 ); // false
  6. isFloat( NaN ); // false
  7. isFloat( Infinity ); // false

Note: It may seem strange, but Infinity should neither be considered an integer nor a float.

ES6 also defines a Number.isSafeInteger(..) utility, which checks to make sure the value is both an integer and within the range of Number.MIN_SAFE_INTEGER-Number.MAX_SAFE_INTEGER (inclusive).

  1. var x = Math.pow( 2, 53 ),
  2. y = Math.pow( -2, 53 );
  3. Number.isSafeInteger( x - 1 ); // true
  4. Number.isSafeInteger( y + 1 ); // true
  5. Number.isSafeInteger( x ); // false
  6. Number.isSafeInteger( y ); // false