From: Jordan Eldredge Date: Sun, 6 Nov 2016 04:07:49 +0000 (-0700) Subject: Introduce isNumber function X-Git-Tag: 2.16.0~5^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=83dedaad2deb4fa9d32e6e3cf9d0e1c13b3a0c0c;p=thirdparty%2Fmoment.git Introduce isNumber function In #3559 @ichernev stated that he would prefer using an `isNumber` utility function over a naive type check. This pull request actualizes that preference. Our new `isNumber` function is slightly more robust than a simple type check. For example, it will also correctly identify wrapped number primitives. https://javascriptweblog.wordpress.com/2010/09/27/the-secret-life-of-javascript-primitives/ --- diff --git a/src/lib/create/from-anything.js b/src/lib/create/from-anything.js index b81295226..ae76f8544 100644 --- a/src/lib/create/from-anything.js +++ b/src/lib/create/from-anything.js @@ -1,6 +1,7 @@ import isArray from '../utils/is-array'; import isObject from '../utils/is-object'; import isObjectEmpty from '../utils/is-object-empty'; +import isNumber from '../utils/is-number'; import isDate from '../utils/is-date'; import map from '../utils/map'; import { createInvalid } from './valid'; @@ -75,7 +76,7 @@ function configFromInput(config) { configFromArray(config); } else if (typeof(input) === 'object') { configFromObject(config); - } else if (typeof(input) === 'number') { + } else if (isNumber(input)) { // from milliseconds config._d = new Date(input); } else { diff --git a/src/lib/duration/create.js b/src/lib/duration/create.js index 354a5e0fa..09af9e24f 100644 --- a/src/lib/duration/create.js +++ b/src/lib/duration/create.js @@ -1,4 +1,5 @@ import { Duration, isDuration } from './constructor'; +import isNumber from '../utils/is-number'; import toInt from '../utils/to-int'; import absRound from '../utils/abs-round'; import hasOwnProp from '../utils/has-own-prop'; @@ -28,7 +29,7 @@ export function createDuration (input, key) { d : input._days, M : input._months }; - } else if (typeof input === 'number') { + } else if (isNumber(input)) { duration = {}; if (key) { duration[key] = input; diff --git a/src/lib/locale/lists.js b/src/lib/locale/lists.js index 4fced6ec5..42f7572e2 100644 --- a/src/lib/locale/lists.js +++ b/src/lib/locale/lists.js @@ -1,3 +1,4 @@ +import isNumber from '../utils/is-number'; import { getLocale } from './locales'; import { createUTC } from '../create/utc'; @@ -8,7 +9,7 @@ function get (format, index, field, setter) { } function listMonthsImpl (format, index, field) { - if (typeof format === 'number') { + if (isNumber(format)) { index = format; format = undefined; } @@ -37,7 +38,7 @@ function listMonthsImpl (format, index, field) { // (true, fmt) function listWeekdaysImpl (localeSorted, format, index, field) { if (typeof localeSorted === 'boolean') { - if (typeof format === 'number') { + if (isNumber(format)) { index = format; format = undefined; } @@ -48,7 +49,7 @@ function listWeekdaysImpl (localeSorted, format, index, field) { index = format; localeSorted = false; - if (typeof format === 'number') { + if (isNumber(format)) { index = format; format = undefined; } diff --git a/src/lib/parse/token.js b/src/lib/parse/token.js index 781b9cf3a..24b4474f8 100644 --- a/src/lib/parse/token.js +++ b/src/lib/parse/token.js @@ -1,4 +1,5 @@ import hasOwnProp from '../utils/has-own-prop'; +import isNumber from '../utils/is-number'; import toInt from '../utils/to-int'; var tokens = {}; @@ -8,7 +9,7 @@ export function addParseToken (token, callback) { if (typeof token === 'string') { token = [token]; } - if (typeof callback === 'number') { + if (isNumber(callback)) { func = function (input, array) { array[callback] = toInt(input); }; diff --git a/src/lib/units/month.js b/src/lib/units/month.js index 5d5ec5747..e454d678a 100644 --- a/src/lib/units/month.js +++ b/src/lib/units/month.js @@ -9,6 +9,7 @@ import { hooks } from '../utils/hooks'; import { MONTH } from './constants'; import toInt from '../utils/to-int'; import isArray from '../utils/is-array'; +import isNumber from '../utils/is-number'; import indexOf from '../utils/index-of'; import { createUTC } from '../create/utc'; import getParsingFlags from '../create/parsing-flags'; @@ -180,7 +181,7 @@ export function setMonth (mom, value) { } else { value = mom.localeData().monthsParse(value); // TODO: Another silent failure? - if (typeof value !== 'number') { + if (!isNumber(value)) { return mom; } } diff --git a/src/lib/utils/is-number.js b/src/lib/utils/is-number.js new file mode 100644 index 000000000..e34c783b0 --- /dev/null +++ b/src/lib/utils/is-number.js @@ -0,0 +1,3 @@ +export default function isNumber(input) { + return typeof value === 'number' || Object.prototype.toString.call(input) === '[object Number]'; +} diff --git a/src/test/moment/is_number.js b/src/test/moment/is_number.js new file mode 100644 index 000000000..c6974c09c --- /dev/null +++ b/src/test/moment/is_number.js @@ -0,0 +1,28 @@ +import { module, test } from '../qunit'; +import isNumber from '../../lib/utils/is-number.js'; + + +test('isNumber recognizes numbers', function (assert) { + assert.ok(isNumber(1), 'simple integer'); + assert.ok(isNumber(0), 'simple number'); + assert.ok(isNumber(-0), 'silly number'); + assert.ok(isNumber(1010010293029), 'large number'); + assert.ok(isNumber(Infinity), 'largest number'); + assert.ok(isNumber(-Infinity), 'smallest number'); + assert.ok(isNumber(NaN), 'not number'); + assert.ok(isNumber(1.100393830000), 'decimal numbers'); + assert.ok(isNumber(Math.LN2), 'natural log of two'); + assert.ok(isNumber(Math.PI), 'delicious number'); + assert.ok(isNumber(5e10), 'scientifically notated number'); + assert.ok(isNumber(new Number(1)), 'number primitive wrapped in an object'); // jshint ignore:line +}); + +test('isNumber rejects non-numbers', function (assert) { + assert.ok(!isNumber(), 'nothing'); + assert.ok(!isNumber(undefined), 'undefined'); + assert.ok(!isNumber(null), 'null'); + assert.ok(!isNumber([1]), 'array'); + assert.ok(!isNumber('[1,2,3]'), 'string'); + assert.ok(!isNumber(new Date()), 'date'); + assert.ok(!isNumber({a:1,b:2}), 'object'); +});