【问题标题】:Why does isNaN(" ") (string with spaces) equal false?为什么 isNaN(" ")(带空格的字符串)等于 false?
【发布时间】:2010-10-23 22:45:58
【问题描述】:

在 JavaScript 中,为什么 isNaN(" ") 的计算结果为 false,而 isNaN(" x") 的计算结果为 true

我正在对文本输入字段执行数字运算,并检查该字段是null"" 还是NaN。当有人在该字段中键入少量空格时,我的三个验证都失败了,我很困惑为什么它会通过isNaN 检查。

【问题讨论】:

  • 嗯...不太清楚主题的另一半去了哪里。它应该是“JavaScript:为什么 isNaN(" ") 评估为假?”
  • 天哪,这就是行为(isNaN 为空或空格返回 false),但我没有找到此函数的确切规格。
  • 这里有一个问题可以回答这个问题:http://stackoverflow.com/questions/115548/why-is-isnannull-false-in-js
  • Javascript 在这些问题上看起来像巫术!你永远不知道,解释总是很复杂。 "" == false // trueisNaN(" ") // false
  • 改用Number.isNaN

标签: javascript nan


【解决方案1】:

我使用以下。

x=(isNaN(parseFloat(x)))? 0.00 : parseFloat(x);

【讨论】:

    【解决方案2】:

    let isNotNumber = val => isNaN(val) || (val.trim && val.trim() === '');
    
    console.log(isNotNumber(' '));
    console.log(isNotNumber('1'));
    console.log(isNotNumber('123x'));
    console.log(isNotNumber('x123'));
    console.log(isNotNumber('0'));
    console.log(isNotNumber(3));
    console.log(isNotNumber('    x'));
    console.log(isNotNumber('1.23'));
    console.log(isNotNumber('1.23.1.3'));
    
    if(!isNotNumber(3)){
      console.log('This is a number');
    }

    【讨论】:

      【解决方案3】:

      我发现有一个特定于 Number 类的方法很方便(因为像 parseInt 这样进行转换的其他函数对其中一些值有不同的输出)并使用原型继承。

      Object.assign(Number.prototype, {
        isNumericallyValid(num) {
          if (
            num === null
            || typeof num === 'boolean'
            || num === ''
            || Number.isNaN(Number(num))
          ) {
            return false;
          }
          return true;
        }
      });
      

      【讨论】:

        【解决方案4】:

        当检查某个带有空格或" "的字符串值是否为isNaN时,可能会尝试执行字符串验证,例如:

        // value = "123 " if (value.match(/\s/) || isNaN(value)) { // do something }

        【讨论】:

          【解决方案5】:

          NaN !== "不是数字"

          NaN是数字类型的值

          这是 ECMAScript 中 isNaN() 的定义

          1. Let num be ToNumber(number).
          2. ReturnIfAbrupt(num).
          3. If num is NaN, return true.
          4. Otherwise, return false.
          

          尝试将任何值转换为数字。

          Number(" ") // 0
          Number("x") // NaN
          Number(null) // 0
          

          如果要判断该值是否为NaN,应先尝试将其转换为数值。

          【讨论】:

            【解决方案6】:

            我用这个

                function isNotANumeric(val) {
                	if(val.trim && val.trim() == "") {
                     return true;
                  } else {
                  	 return isNaN(parseFloat(val * 1));
                  }
                }
                
                alert(isNotANumeric("100"));  // false
                alert(isNotANumeric("1a"));   // true
                alert(isNotANumeric(""));     // true
                alert(isNotANumeric("   "));  // true

            【讨论】:

              【解决方案7】:

              正如其他解释的那样,isNaN 函数将在验证之前将空字符串强制转换为数字,从而将空字符串更改为 0(这是一个有效数字)。 但是,我发现parseInt 函数在尝试解析空字符串或只有空格的字符串时会返回NaN。因此,以下组合似乎运作良好:

              if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');

              此检查适用于正数、负数和带小数点的数字,因此我相信它涵盖了所有常见的数字情况。

              【讨论】:

                【解决方案8】:

                isNAN(<argument>) 是一个判断给定参数是否为非法数字的函数。 isNaN 将参数类型转换为 Number 类型。如果要检查参数是否为数字?请在jQuery中使用$.isNumeric()函数。

                即 isNaN(foo) 等价于 isNaN(Number(foo)) 出于显而易见的原因,它接受任何将所有数字都作为数字的字符串。例如。

                isNaN(123) //false
                isNaN(-1.23) //false
                isNaN(5-2) //false
                isNaN(0) //false
                isNaN('123') //false
                isNaN('Hello') //true
                isNaN('2005/12/12') //true
                isNaN('') //false
                isNaN(true) //false
                isNaN(undefined) //true
                isNaN('NaN') //true
                isNaN(NaN) //true
                isNaN(0 / 0) //true
                

                【讨论】:

                  【解决方案9】:

                  JavaScript 内置 isNaN 函数 - 正如默认情况下所预期的 - 一个“动态类型运算符”。 因此(在 DTC 过程中)可能产生简单真 | 的所有值。 false 如"", " ", " 000",不能为NaN。

                  表示提供的参数将首先进行转换,如:

                  function isNaNDemo(arg){
                     var x = new Number(arg).valueOf();
                     return x != x;
                  }
                  

                  说明:

                  在函数体的第一行,我们(首先)尝试将参数成功转换为数字对象。并且(第二),我们使用点运算符 - 为了我们自己的方便 - 立即剥离所创建对象的 primitive

                  第二行,我们取上一步得到的值,利用NaN不等于宇宙中的任何东西,甚至对自己也不行,例如:NaN == NaN >> false 最终将其(不等式)与自己进行比较。

                  只有当且仅当提供的参数返回是尝试转换为数字对象失败时,函数返回才会产生 true,即,一个非数字数字;例如,NaN。


                  isNaNstatic( )

                  但是,对于静态类型运算符 - 如果需要和需要时 - 我们可以编写一个更简单的函数,例如:

                  function isNaNstatic(x){   
                     return x != x;
                  }
                  

                  并完全避免 DTC,这样如果参数不是明确的 NaN 数,它将返回 false。因此,针对以下内容进行测试:

                  isNaNStatic(" x"); // will return false 因为它仍然是一个字符串。

                  但是: isNaNStatic(1/"x"); // will of course return true.isNaNStatic(NaN); >> true 一样。

                  但与isNaN相反,isNaNStatic("NaN"); >> false 因为它(参数)是一个普通字符串。

                  附言: isNaN 的静态版本在现代编码场景中非常有用。这很可能是我花时间发布此内容的主要原因之一。

                  问候。

                  【讨论】:

                    【解决方案10】:

                    来自MDN 您所面临问题的原因

                    当 isNaN 函数的参数不是 Number 类型时,该值首先被强制转换为 Number。然后测试结果值以确定它是否为 NaN。

                    您可能需要检查以下综合答案,该答案还涵盖了 NaN 比较是否相等。

                    How to test if a JavaScript variable is NaN

                    【讨论】:

                      【解决方案11】:

                      不完全正确的答案

                      Antonio Haley 的 highly upvoted and accepted answer 在这里错误地假设此过程通过 JavaScript 的 parseInt 函数:

                      你可以在字符串上使用 parseInt ... 结果应该是失败的 isNAN。

                      我们可以很容易地用字符串"123abc"来反驳这个说法:

                      parseInt("123abc")    // 123     (a number...
                      isNaN("123abc")       // true     ...which is not a number)
                      

                      这样,我们可以看到 JavaScript 的 parseInt 函数返回 "123abc" 作为数字 123,但它的 isNaN 函数告诉我们 "123abc" 不是数字.

                      正确答案

                      ECMAScript-262 定义了 isNaN 检查在 section 18.2.3 中的工作方式。

                      18.2.3 isNaN(号码)

                      isNaN 函数是 %isNaN% 内部对象。当isNaN函数用一个参数号调用时,采取以下步骤:

                      1. num 成为? ToNumber(number).
                      2. 如果numNaN,则返回true
                      3. 否则,返回false

                      它引用的@​​987654343@ 函数也在ECMAScript-262's section 7.1.3 中定义。在这里,我们了解到 JavaScript 如何处理传递给该函数的字符串。

                      问题中给出的第一个示例是一个只包含空格字符的字符串。本节规定:

                      为空或仅包含空格的StringNumericLiteral 将转换为+0

                      " " 示例字符串因此被转换为+0,这是一个数字。

                      同一部分还指出:

                      如果语法不能将String 解释为StringNumericLiteral 的扩展,那么ToNumber 的结果就是NaN

                      如果不引用该部分中包含的所有检查,则问题中给出的" x" 示例属于上述条件,因为它不能被解释为StringNumericLiteral" x" 因此转换为 NaN

                      【讨论】:

                        【解决方案12】:

                        我写了这个快速的小函数来帮助解决这个问题。

                        function isNumber(val) {
                             return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
                        };
                        

                        它只检查任何非数字 (0-9)、非“-”或“.”、非未定义、null 或空字符,如果没有匹配则返回 true。 :)

                        【讨论】:

                        • 迟来的感谢您;这很好地解决了我的问题。
                        【解决方案13】:

                        isNaN 函数需要一个数字作为其参数,因此任何其他类型的参数(在您的情况下为字符串)将在执行实际函数逻辑之前转换为数字。 (注意NaN 也是 Number 类型的值!)

                        顺便说一句。这对于 所有 内置函数很常见 - 如果它们需要特定类型的参数,则实际参数将使用标准转换函数进行转换。所有基本类型(bool、string、number、object、date、null、undefined)之间都有标准转换。

                        StringNumber 的标准转换可以用Number() 显式调用。所以我们可以看到:

                        • Number(" ") 计算结果为 0
                        • Number(" x") 评估为 NaN

                        鉴于此,isNaN 函数的结果完全合乎逻辑!

                        真正的问题是为什么标准的字符串到数字的转换会像现在这样工作。字符串到数字的转换实际上是为了将像“123”或“17.5e4”这样的数字字符串转换为等效的数字。转换首先跳过初始空白(因此“123”有效),然后尝试将其余部分解析为数字。如果它不能解析为数字(“x”不是),则结果为 NaN。但是有一个明确的特殊规则,一个空字符串或只有空格的字符串被转换为 0。所以这解释了转换。

                        参考:http://www.ecma-international.org/ecma-262/5.1/#sec-9.3.1

                        【讨论】:

                          【解决方案14】:

                          isNaN(" ") 为 false 是 isNaN 全局函数令人困惑的行为的一部分,因为它会将非数字强制转换为数字类型。

                          来自MDN

                          自从 isNaN 函数规范的最早版本以来,它对非数字参数的行为一直令人困惑。当isNaN 函数的参数不是数字类型时,首先将值强制转换为数字。然后测试结果值以确定它是否为NaN。因此,对于非数字,当强制转换为数字类型时会产生一个有效的非 NaN 数值(特别是空字符串和布尔基元,当强制转换为数字值 0 或 1)时,“false”返回值可能是意料之外的;例如,空字符串肯定是“不是数字”。

                          还要注意,在 ECMAScript 6 中,现在还有 Number.isNaN 方法,根据 MDN:

                          与全局isNaN() 函数相比,Number.isNaN() 不存在将参数强制转换为数字的问题。这意味着现在可以安全地传递通常会转换为NaN 但实际上与NaN 不同的值。这也意味着只有类型编号的值,也就是NaN,才返回true

                          很遗憾

                          即使是 ECMAScript 6 Number.isNaN 方法也有其自身的问题,如博客文章 - Fixing the ugly JavaScript and ES6 NaN problem 中所述。

                          【讨论】:

                            【解决方案15】:

                            函数isNaN("") 执行字符串到数字类型强制

                            ECMAScript 3-5 defines the following return values for the typeof operator:

                            • 未定义
                            • 对象(空、对象、数组)
                            • 布尔值
                            • 号码
                            • 字符串
                            • 功能

                            最好将我们的测试包装在一个函数体中:

                            function isNumber (s) {
                                return typeof s == 'number'? true
                                       : typeof s == 'string'? (s.trim() === ''? false : !isNaN(s))
                                       : (typeof s).match(/object|function/)? false
                                       : !isNaN(s)
                            }
                            

                            这个函数不是为了测试变量type,而是测试强制值。例如,布尔值和字符串被强制转换为数字,因此您可能希望将此函数称为 isNumberCoerced()

                            如果除了 stringnumber 之外不需要测试 types,那么下面的 sn-p 可以用作一些条件:

                            if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
                                alert("s is a number")
                            

                            【讨论】:

                              【解决方案16】:

                              怎么样

                              function isNumberRegex(value) {        
                                  var pattern = /^[-+]?\d*\.?\d*$/i;
                                  var match = value.match(pattern);
                                  return value.length > 0 && match != null;
                              }
                              

                              【讨论】:

                                【解决方案17】:

                                您可能会感到惊讶,也可能不会,但这里有一些测试代码可以向您展示 JavaScript 引擎的古怪之处。

                                document.write(isNaN("")) // false
                                document.write(isNaN(" "))  // false
                                document.write(isNaN(0))  // false
                                document.write(isNaN(null)) // false
                                document.write(isNaN(false))  // false
                                document.write("" == false)  // true
                                document.write("" == 0)  // true
                                document.write(" " == 0)  // true
                                document.write(" " == false)  // true
                                document.write(0 == false) // true
                                document.write(" " == "") // false
                                

                                所以这意味着

                                " " == 0 == false
                                

                                "" == 0 == false
                                

                                但是

                                "" != " "
                                

                                玩得开心:)

                                【讨论】:

                                • +1 很棒的帖子。您能否在此处添加三等号(=== 和 !==)运算符的适用方式?
                                • 你应该试试 NaN===NaN 或 NaN==NaN;-) 我不知道这一切是否意味着 javascript 引擎很古怪,或者 javascript 对古怪的程序员不利。跨度>
                                • @Kooilnc 事实上 NaN != NaN 实际上是一次不错的选择。这个想法是,NaN 几乎总是一个与程序员预期不同的计算结果,并且假设两个“错误”的计算结果相等是非常危险的,我会说。
                                • @Kooilnc 一点也不想带走 javascript 的古怪之处,但这些 NaN 只是遵守 IEEE 754 浮点标准。您可以像往常一样在大 W 上阅读所有相关信息:en.wikipedia.org/wiki/NaN
                                • 很棒的帖子,但没有解释“为什么”。
                                【解决方案18】:

                                这个功能似乎在我的测试中有效

                                function isNumber(s) {
                                    if (s === "" || s === null) {
                                        return false;
                                    } else {
                                        var number = parseInt(s);
                                        if (number == 'NaN') {
                                            return false;
                                        } else {
                                            return true;
                                        }
                                    }
                                }
                                

                                【讨论】:

                                • 你的整个函数可以写成:return !(s === "" || s === null || parseInt(s) == 'NaN');
                                【解决方案19】:

                                如果你真的想正确检查它是否是整数,我建议你使用以下函数:

                                function isInteger(s)
                                {
                                   return Math.ceil(s) == Math.floor(s);
                                }
                                

                                【讨论】:

                                  【解决方案20】:

                                  如果您想实现一个准确的 isNumber 函数,这是 Douglas Crockford 的 Javascript: The Good Parts [第 105 页] 中的一种方法

                                  var isNumber = function isNumber(value) {
                                     return typeof value === 'number' && 
                                     isFinite(value);
                                  }
                                  

                                  【讨论】:

                                  • @Xyan 在这种情况下,此函数对于执行 OP 要求执行的任务不是很有帮助,即检查数字的字符串表示...
                                  • 对字符串字面量(例如“number”)使用任何给定值的所谓严格相等运算符是愚蠢的,
                                  【解决方案21】:

                                  为了更好地理解它,请打开第 43 页“ToNumber 应用于字符串类型”的Ecma-Script spec pdf

                                  如果字符串具有数字语法,可以包含任意数量的空白字符,则可以将其转换为数字类型。空字符串的计算结果为 0。字符串 'Infinity' 也应该给出

                                  isNaN('Infinity'); // false
                                  

                                  【讨论】:

                                    【解决方案22】:

                                    我不确定为什么,但为了解决这个问题,您总是可以在检查之前修剪空白。无论如何,您可能都想这样做。

                                    【讨论】:

                                    • 修剪后的空字符串也无法通过 isNaN 测试。
                                    【解决方案23】:

                                    我认为这是因为 Javascript 的输入:' ' 被转换为零,而 'x' 不是:

                                    alert(' ' * 1); // 0
                                    alert('x' * 1); // NaN
                                    

                                    【讨论】:

                                      【解决方案24】:

                                      尝试使用:

                                      alert(isNaN(parseInt("   ")));
                                      

                                      或者

                                      alert(isNaN(parseFloat("    ")));
                                      

                                      【讨论】:

                                      • 嗨,先生,isNaN(parseInt("123a")) :如果字符串包含 aplha numeric,将返回 123,因此您的解决方案将不起作用
                                      【解决方案25】:

                                      JavaScript 将空字符串解释为 0,然后 isNAN 测试失败。您可以先在字符串上使用 parseInt,它不会将空字符串转换为 0。然后结果应该失败 isNAN。

                                      【讨论】:

                                      • 但是 parseInt("123abcd") 返回 123,这意味着 isNaN(parseInt("123abcd")) 将返回 false 而它应该返回 true!
                                      • 那么 (IsNaN(string) || isNaN(parseInt(string))) 怎么样
                                      • 解释isNaN(arg)有两个步骤。 1) 将 arg 转换为数字,2) 检查该数字是否为数值 NaN。这有助于我更好地理解它。
                                      • @Antonio_Haley 等一下,我不明白。如果“JavaScript 将空字符串解释为 0”,为什么 parseInt("") 返回 NaN?
                                      • @Jean-François 你说得对,更正确的说法是“isNaN 将空字符串解释为 0”,而不是 JavaScript 本身。
                                      猜你喜欢
                                      • 1970-01-01
                                      • 2012-02-15
                                      • 2016-04-19
                                      • 2010-09-12
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2016-12-22
                                      • 2021-12-13
                                      • 2021-10-26
                                      相关资源
                                      最近更新 更多