Как проверить, является ли число NaN в JavaScript? - PullRequest
377 голосов
/ 16 апреля 2010

Я пробовал это только в консоли JavaScript Firefox, но ни одно из следующих утверждений не возвращает true:

parseFloat('geoff') == NaN;

parseFloat('geoff') == Number.NaN;

Ответы [ 30 ]

533 голосов
/ 16 апреля 2010

Попробуйте этот код:

isNaN(parseFloat("geoff"))

Чтобы проверить, является ли любое значение NaN, а не просто числами, см. Здесь: Как вы проверяете NaN в Javascript?

135 голосов
/ 07 июня 2013

Я только что столкнулся с этой техникой в ​​книге Эффективный JavaScript , который довольно прост:

Поскольку NaN является единственным значением JavaScript, которое рассматривается как неравное для себя, вы всегда можете проверить, является ли значение NaN, проверив его на равенство с самим собой:

var a = NaN;
a !== a; // true 

var b = "foo";
b !== b; // false 

var c = undefined; 
c !== c; // false

var d = {};
d !== d; // false

var e = { valueOf: "foo" }; 
e !== e; // false

Не осознавал этого, пока не прокомментировал @allsyed, но это в спецификации ECMA: https://tc39.github.io/ecma262/#sec-isnan-number

50 голосов
/ 16 апреля 2010

Используйте этот код:

isNaN('geoff');

См. isNaN() документы по MDN .

alert ( isNaN('abcd'));  // alerts true
alert ( isNaN('2.0'));  // alerts false
alert ( isNaN(2.0));  // alerts false
40 голосов
/ 21 августа 2015

Поскольку значение типа Number должно быть проверено, является ли оно NaN или нет, глобальная функция isNaN выполнит работу

isNaN(any-Number);

Для общего подхода, который работает для всех типов в JS, мы можем использовать любое из следующего:

Для пользователей ECMAScript-5:

#1
if(x !== x) {
    console.info('x is NaN.');
}
else {
    console.info('x is NOT a NaN.');
}

Для людей, использующих ECMAScript-6:

#2
Number.isNaN(x);

И для целей согласованности в ECMAScript 5 и 6, мы также можем использовать это polyfill для Number.isNan

#3
//Polyfill from MDN
Number.isNaN = Number.isNaN || function(value) {
    return typeof value === "number" && isNaN(value);
}
// Or
Number.isNaN = Number.isNaN || function(value) {     
    return value !== value;
}

пожалуйста, проверьте Этот ответ для более подробной информации.

16 голосов
/ 08 января 2013

NaN - это особое значение, которое не может быть протестировано таким образом. Интересная вещь, которой я просто хотел поделиться, это

var nanValue = NaN;
if(nanValue !== nanValue) // Returns true!
    alert('nanValue is NaN');

Возвращает true только для значений NaN и является безопасным способом тестирования. Должен определенно быть обернут в функцию или хотя бы прокомментирован, потому что, очевидно, не имеет смысла проверять, не совпадают ли одна и та же переменная, хе-хе.

14 голосов
/ 16 апреля 2010

Вы должны использовать глобальный вызов функции isNaN(value), потому что:

  • Поддерживается кросс-браузер
  • См. isNaN для документации

Примеры:

 isNaN('geoff'); // true
 isNaN('3'); // false

Надеюсь, это поможет вам.

12 голосов
/ 28 декабря 2015

Начиная с ES6 , Object.is(..) - это новая утилита, которую можно использовать для проверки двух значений на абсолютное равенство:

var a = 3 / 'bar';
Object.is(a, NaN); // true
8 голосов
/ 17 марта 2014

Чтобы устранить проблему, из-за которой '1.2geoff' анализируется, просто используйте взамен Number().

Так что вместо этого:

parseFloat('1.2geoff'); // => 1.2
isNaN(parseFloat('1.2geoff')); // => false
isNaN(parseFloat('.2geoff')); // => false
isNaN(parseFloat('geoff')); // => true

Сделайте это:

Number('1.2geoff'); // => NaN
isNaN(Number('1.2geoff')); // => true
isNaN(Number('.2geoff')); // => true
isNaN(Number('geoff')); // => true

РЕДАКТИРОВАТЬ: я только что заметил еще одну проблему из этого, хотя ... ложные значения (и истина как настоящий логический) передаются в Number() возвращают как 0! В этом случае ... parseFloat работает каждый раз вместо этого. Итак, вернемся к этому:

function definitelyNaN (val) {
    return isNaN(val && val !== true ? Number(val) : parseFloat(val));
}

И это охватывает, казалось бы, все. Я оценил его на 90% медленнее, чем _.isNaN Лодаша, но тогда он не охватывает все NaN:

http://jsperf.com/own-isnan-vs-underscore-lodash-isnan

Просто чтобы прояснить, моя заботится о человеческой буквальной интерпретации чего-то, что является "не числом", а Лодаш заботится о компьютерной буквальной интерпретации проверки, является ли что-то "NaN".

7 голосов
/ 25 августа 2013

Хотя ответ @chiborg верен, следует отметить еще кое-что:

parseFloat('1.2geoff'); // => 1.2
isNaN(parseFloat('1.2geoff')); // => false
isNaN(parseFloat('.2geoff')); // => false
isNaN(parseFloat('geoff')); // => true

Суть в том, что если вы используете этот метод для проверки ввода, результат будет довольно либеральным.

Итак, да, вы можете использовать parseFloat(string) (или в случае полных чисел parseInt(string, radix) ', а затем затем обернуть это с isNaN(), но помните о гоче с числами, переплетенными дополнительными нечисловыми символами.

6 голосов
/ 21 января 2015

Простое решение!

ДЕЙСТВИТЕЛЬНО супер просто! Вот! Есть этот метод!

function isReallyNaN(a) { return a !== a; };

Используйте так же просто, как:

if (!isReallyNaN(value)) { return doingStuff; }

См. Тест производительности здесь с использованием этой функции против выбранный ответ

Также: см. Ниже 1-й пример для пары альтернативных реализаций.


Пример:

function isReallyNaN(a) { return a !== a; };

var example = {
    'NaN': NaN,
    'an empty Objet': {},
    'a parse to NaN': parseFloat('$5.32'),
    'a non-empty Objet': { a: 1, b: 2 },
    'an empty Array': [],
    'a semi-passed parse': parseInt('5a5'),
    'a non-empty Array': [ 'a', 'b', 'c' ],
    'Math to NaN': Math.log(-1),
    'an undefined object': undefined
  }

for (x in example) {
    var answer = isReallyNaN(example[x]),
        strAnswer = answer.toString();
    $("table").append($("<tr />", { "class": strAnswer }).append($("<th />", {
        html: x
    }), $("<td />", {
        html: strAnswer
    })))
};
table { border-collapse: collapse; }
th, td { border: 1px solid; padding: 2px 5px; }
.true { color: red; }
.false { color: green; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table></table>

Существует несколько альтернативных путей, которые вы выбираете для реализации, если вы не хотите использовать метод с альтернативным именем и хотите, чтобы он был более глобально доступным. Предупреждение Эти решения включают изменение собственных объектов и могут быть не лучшим решением. Всегда соблюдайте осторожность и помните, что другие библиотеки, которые вы можете использовать, могут зависеть от собственного кода или подобных изменений.

Альтернативная реализация 1: заменить собственный метод isNaN.

//  Extremely simple. Just simply write the method.
window.isNaN = function(a) { return a !==a; }

Альтернативная реализация 2: добавление к объекту нумерации
* Рекомендуется, так как он также является полизаполнением для ECMA 5–6

Number['isNaN'] || (Number.isNaN = function(a) { return a !== a });
//  Use as simple as
Number.isNaN(NaN)

Альтернативный раствор тест, если пустой

Простой оконный метод, который я написал, чтобы проверить, является ли объект Пусто . Это немного отличается от того, что не дает, если элемент "точно" NaN , но я решил, что я выброшу это, поскольку это также может быть полезно при поиске пустых элементов.

/** isEmpty(varried)
 *  Simple method for testing if item is "empty"
 **/
;(function() {
   function isEmpty(a) { return (!a || 0 >= a) || ("object" == typeof a && /\{\}|\[(null(,)*)*\]/.test(JSON.stringify(a))); };
   window.hasOwnProperty("empty")||(window.empty=isEmpty);
})();
* * Пример тысяча шестьдесят три:

;(function() {
   function isEmpty(a) { return !a || void 0 === a || a !== a || 0 >= a || "object" == typeof a && /\{\}|\[(null(,)*)*\]/.test(JSON.stringify(a)); };
   window.hasOwnProperty("empty")||(window.empty=isEmpty);
})();

var example = {
    'NaN': NaN,
    'an empty Objet': {},
    'a parse to NaN': parseFloat('$5.32'),
    'a non-empty Objet': { a: 1, b: 2 },
    'an empty Array': new Array(),
    'an empty Array w/ 9 len': new Array(9),
    'a semi-passed parse': parseInt('5a5'),
    'a non-empty Array': [ 'a', 'b', 'c' ],
    'Math to NaN': Math.log(-1),
    'an undefined object': undefined
  }

for (x in example) {
	var answer = empty(example[x]),
		strAnswer = answer.toString();
	$("#t1").append(
		$("<tr />", { "class": strAnswer }).append(
			$("<th />", { html: x }),
			$("<td />", { html: strAnswer.toUpperCase() })
		)
	)
};


function isReallyNaN(a) { return a !== a; };
for(x in example){var answer=isReallyNaN(example[x]),strAnswer=answer.toString();$("#t2").append($("<tr />",{"class":strAnswer}).append($("<th />",{html:x}),$("<td />",{html:strAnswer.toUpperCase()})))};
table { border-collapse: collapse; float: left; }
th, td { border: 1px solid; padding: 2px 5px; }
.true { color: red; }
.false { color: green; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="t1"><thead><tr><th colspan="2">isEmpty()</th></tr></thead><thead><tr><th>Value Type</th><th>Bool Return</th></tr></thead></table>
<table id="t2"><thead><tr><th colspan="2">isReallyNaN()</th></tr></thead><thead><tr><th>Value Type</th><th>Bool Return</th></tr></thead></table>

Чрезвычайно глубокая проверка, если пусто

Этот последний идет немного глубже, даже проверяя, не заполнен ли объект пустыми объектами. Я уверен, что в нем есть место для улучшений и возможных ям, но пока что, похоже, ловит почти все.

function isEmpty(a) {
	if (!a || 0 >= a) return !0;
	if ("object" == typeof a) {
		var b = JSON.stringify(a).replace(/"[^"]*":(0|"0*"|false|null|\{\}|\[(null(,)?)*\]),?/g, '').replace(/"[^"]*":\{\},?/g, '');
		if ( /^$|\{\}|\[\]/.test(b) ) return !0;
		else if (a instanceof Array)  {
			b = b.replace(/(0|"0*"|false|null|\{\}|\[(null(,)?)*\]),?/g, '');
			if ( /^$|\{\}|\[\]/.test(b) ) return !0;
		}
	}
	return false;
}
window.hasOwnProperty("empty")||(window.empty=isEmpty);

var example = {
    'NaN': NaN,
    'an empty Objet': {},
    'a parse to NaN': parseFloat('$5.32'),
    'a non-empty Objet': { a: 1, b: 2 },
    'an empty Array': new Array(),
    'an empty Array w/ 9 len': new Array(9),
    'a semi-passed parse': parseInt('5a5'),
    'a non-empty Array': [ 'a', 'b', 'c' ],
    'Math to NaN': Math.log(-1),
    'an undefined object': undefined,
    'Object Full of Empty Items': { 1: '', 2: [], 3: {}, 4: false, 5:new Array(3), 6: NaN, 7: null, 8: void 0, 9: 0, 10: '0', 11: { 6: NaN, 7: null, 8: void 0 } },
    'Array Full of Empty Items': ["",[],{},false,[null,null,null],null,null,null,0,"0",{"6":null,"7":null}]
  }

for (x in example) {
	var answer = empty(example[x]),
		strAnswer = answer.toString();
	$("#t1").append(
		$("<tr />", { "class": strAnswer }).append(
			$("<th />", { html: x }),
			$("<td />", { html: strAnswer.toUpperCase() })
		)
	)
};


function isReallyNaN(a) { return a !== a; };
for(x in example){var answer=isReallyNaN(example[x]),strAnswer=answer.toString();$("#t2").append($("<tr />",{"class":strAnswer}).append($("<th />",{html:x}),$("<td />",{html:strAnswer.toUpperCase()})))};
table { border-collapse: collapse; float: left; }
th, td { border: 1px solid; padding: 2px 5px; }
.true { color: red; }
.false { color: green; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="t1"><thead><tr><th colspan="2">isEmpty()</th></tr></thead><thead><tr><th>Value Type</th><th>Bool Return</th></tr></thead></table>
<table id="t2"><thead><tr><th colspan="2">isReallyNaN()</th></tr></thead><thead><tr><th>Value Type</th><th>Bool Return</th></tr></thead></table>
...