在JavaScript中如何检查一个数字是否为NaN?

544

我只在Firefox的JavaScript控制台中尝试过,但以下语句都没有返回true:

parseFloat('geoff') == NaN;

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

6
如果您的实际目标是检查数字, 这篇文章值得一读:https://dev59.com/3nVD5IYBdhLWcg3wU56H - Paul
3
http://designpepper.com/blog/drips/the-problem-with-testing-for-nan-in-javascript.html - Foreever
1
@Gothdo:好的,但是我确实问过如何检查一个数字是否为NaN,而不是任何值。 - Paul D. Waite
3
@PaulD.Waite 是的,但很多人在谷歌搜索"如何在JavaScript中检查变量是否为NaN"时会来到这里。 - Michał Perłakowski
在ES6(又名ECMAScript 2015)中,使用Number.isNaN,查看此答案MDN - undefined
显示剩余4条评论
33个回答

8

虽然 @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()中,但请注意数字与其他非数字字符交织的陷阱。


1
有趣。有什么方法可以对抗这种情况并检测出“1.2geoff”不是一个有效的数字字符串吗? - Gabe Halsmer
2
请注意,这仅在字符串以数字开头时才会发生。parseFloat('test1.2')将返回NaN - Eduard Luca

6

简单易行的解决方案!

真的超级简单!在这里!使用这个方法!

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

使用起来就像这样简单:

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

点击此处查看使用此函数与所选答案进行的性能测试。

此外:请参见第一个示例以获得一些备选实现。


示例:

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的poly-fill

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>


1
@PaulD.Waite 可能是这个应用程序的问题,但我没有看到被接受的答案。实际上,我只看到大约5个答案,但我看到它说有15个。 - SpYk3HH
1
你在用什么应用程序? - Paul D. Waite
2
@PaulD.Waite 是适用于安卓系统的 SE。在 Galaxy S3 上使用。 - SpYk3HH
1
啊哈。我没有应用程序来查看,但这里是被接受的答案链接:https://dev59.com/OnE85IYBdhLWcg3wtVxT#2652335 - Paul D. Waite
@PaulD.Waite 啊,我明白了。我想,对于这个问题本身的直接回答来说,那个答案可能足够了。我在另一个问题上发布了我的答案,完全是关于“JS如何检查是否为“真正”的NaN”,因为isNaN不可靠。有人在那里评论并告诉我这个问题更适合我的答案,因此将其移动到了这里。只是简单地提供一些与此问题相关的有用信息,这个问题在Google搜索中会出现,“它是NaN吗?”值得一提的是,我的答案比选定答案更准确。 - SpYk3HH

6

function isNotANumber(n) {
  if (typeof n !== 'number') {
    return true;
  } 
  return n !== n;
}


感谢您的帮助! - Jimit Rupani

6
如果您的环境支持ECMAScript 2015,则可能希望使用Number.isNaN确保值确实为NaNisNaN的问题是,如果您将其用于非数字数据,则会应用一些令人困惑的规则(根据MDN)。例如,
isNaN(NaN);       // true
isNaN(undefined); // true
isNaN({});        // true

因此,在支持ECMA Script 2015的环境中,您可能希望使用。
Number.isNaN(parseFloat('geoff'))

7
我的环境只支持 ECMAScript XP Home Edition :((注:ECMAScript XP Home Edition 并非真实存在的编程语言,可能是一种比喻或者玩笑话) - Paul D. Waite
1
@PaulD.Waite(我希望你是指IE 6:D)没问题:-)只要记住isNaN可能会让你陷入麻烦,并记得在ECMAScript 2015环境中使用Number.isNaN :-) - thefourtheye

5

我想分享另一种选择,它不一定比其他选择更好,但我认为值得一看:

function customIsNaN(x) { return (typeof x == 'number' && x != 0 && !x); }

这背后的逻辑是,除了 0NaN 以外的每个数字都会被转换为 true
我进行了快速测试,它的表现与 Number.isNaN 和检查自身是否为假一样好。所有三者的表现都比 isNan 好。
结果如下:
customIsNaN(NaN);            // true
customIsNaN(0/0);            // true
customIsNaN(+new Date('?')); // true

customIsNaN(0);          // false
customIsNaN(false);      // false
customIsNaN(null);       // false
customIsNaN(undefined);  // false
customIsNaN({});         // false
customIsNaN('');         // false

如果您想避免破损的isNaN函数,这可能会很有用。


5

我使用underscore的 isNaN 函数,因为在JavaScript中:

isNaN(undefined) 
-> true

至少要注意那个“陷阱”。


10
我有点困惑。当传入undefined时,为什么isNaN会返回true是错误的行为呢?不是undefined确实不是一个数字吗?请您帮我澄清一下。 - Xaxis
3
@Xaxis NaN不应被视为等同于undefined,它们都是具有特定且不同含义的特殊值。请考虑以下情况:我有一个值,但我不告诉你它是什么,它可能是一个数字,也可能不是,但无论如何,从你的角度来看,它是未定义的。 - Corin
1
@Corin undefined 可能与 NaN 不同,但它仍然不是一个数字,因此 isNaN(undefined) 应该是(并且是)true - neuhaus

4
也许这个也有用:
function isNaNCustom(value){
    return value.toString() === 'NaN' && 
           typeof value !== 'string' && 
           typeof value === 'number'
}

3

似乎Node.js默认不支持isNaN()函数。
我通过以下方法进行了解决:

var value = 1;
if (parseFloat(stringValue)+"" !== "NaN") value = parseFloat(stringValue);

当然可以,但我并不是在问关于Node.js的事情。 - Paul D. Waite

3

2

另一个解决方案提到在 MDN parseFloat页面中。

它提供了一个过滤函数来进行严格的解析。

var filterFloat = function (value) {
    if(/^(\-|\+)?([0-9]+(\.[0-9]+)?|Infinity)$/
      .test(value))
      return Number(value);
  return NaN;
}


console.log(filterFloat('421'));               // 421
console.log(filterFloat('-421'));              // -421
console.log(filterFloat('+421'));              // 421
console.log(filterFloat('Infinity'));          // Infinity
console.log(filterFloat('1.61803398875'));     // 1.61803398875
console.log(filterFloat('421e+0'));            // NaN
console.log(filterFloat('421hop'));            // NaN
console.log(filterFloat('hop1.61803398875'));  // NaN

然后你可以使用isNaN来检查它是否为NaN


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接