왜 NaN (“”) (공백이있는 문자열)이 거짓입니까?


160

자바 스크립트에서, 왜 않는 isNaN(" ")로 평가 false하지만, isNaN(" x")하는 평가 true?

나는 텍스트 입력 필드에 숫자 작업을 수행하고있어, 나는 필드가있는 경우 확인하고있어 null, ""NaN. 누군가 필드에 소수의 공백을 입력하면 세 가지 모두에 대한 유효성 검사가 실패하고 왜 isNaN검사를 통과했는지 혼란 스럽습니다 .


1
흠 ... 주제의 다른 절반이 어디로 갔는지 확실하지 않습니다. "JavaScript : isNaN (" ")이 false로 평가되는 이유는 무엇입니까?"입니다.
IVR 어벤저

Jes, 이것이 동작입니다 (isNaN의 경우 비어 있거나 공백이 false를 반환 함). 그러나이 함수의 정확한 사양을 찾지 못했습니다.
Lucero

여기에 대답하는 질문이 있습니다 : http://stackoverflow.com/questions/115548/why-is-isnannull-false-in-js
Lucero

이 문제에 대한 자바 스크립트는 부두처럼 보입니다! 당신은 결코 알지 못하며 설명은 항상 매우 복잡합니다. "" == false // trueisNaN(" ") // false
주앙 멘텔 페레이라

답변:


155

JavaScript는 빈 문자열을 0으로 해석하여 isNAN 테스트에 실패합니다. 빈 문자열을 0으로 변환하지 않는 문자열에 먼저 parseInt를 사용할 수 있습니다. 그런 다음 isNAN이 실패합니다.


53
그러나 parseInt ( "123abcd")는 123을 반환합니다. 즉 isNaN (parseInt ( "123abcd"))는 true를 반환하지만 false를 반환합니다.
Pawan Nogariya

11
그래서 어떻습니까 (IsNaN (string) || isNaN (parseInt (string)))
matt

5
해석에는 2 단계가 isNaN(arg)있습니다. 1) arg를 숫자로 변환합니다. 2) 해당 숫자가 숫자 값인지 확인합니다 NaN. 그것은 내가 그것을 더 잘 이해하는 데 도움이되었습니다.
xdhmoore

3
@Antonio_Haley 잠깐만, 나는 그것을 얻지 못한다. "JavaScript가 빈 문자열을 0으로 해석"하면 왜 parseInt ( "")가 NaN을 반환합니까?
Jean-François Beauchamp 2016

1
@ Jean-François 당신이 맞습니다.보다 정확한 문장은 "isNaN은 빈 문자열을 0으로 해석합니다."는 JavaScript 자체가 아닙니다.
Antonio Haley

82

놀랍거나 그렇지 않을 수도 있지만 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

그러나

"" != " "

재미있게 보내세요 :)


5
+1 좋은 소식. 트리플 같음 (=== 및! ==) 연산자가 여기에 어떻게 맞는지 추가 할 수 있습니까?
bendewey

2
NaN === NaN 또는 NaN == NaN ;-) 시도해야합니다.이 모든 것이 자바 스크립트 엔진이 엉뚱한 지 또는 자바 스크립트가 엉뚱한 프로그래머에게 나쁜지를 의미하는지 모르겠습니다.
KooiInc 2009

10
@ Kooilnc NaN! = NaN은 사실 한 번만 좋은 선택입니다. NaN은 거의 항상 프로그래머가 의도 한 방식과는 다른 계산의 결과이며, "잘못된"두 계산의 결과가 같다고 가정하는 것은 매우 위험합니다.
skrebbel

2
@Kooilnc는 자바 스크립트의 문제를 조금도 없애지 않지만이 NaN은 IEEE 754 부동 소수점 표준을 준수합니다. 큰 W에서 평소와 같이 모든 내용을 읽을 수 있습니다. en.wikipedia.org/wiki/NaN
Spike0xff 1

@NickBerardi F'ing LOL! 이 게시물을 보니 너무 기뻐요. isNaN 함수가 왜 지연되는지 알아내는 데 도움이되었습니다. 나는 완전히 개발되지 않은 코드에서 그것을 제거 할 것이고, 다시는 사용하지 않을 것입니다. 나는에 대한 유효성을 검사 null, ""그리고 " "나 자신. 감사!
VoidKing

16

더 잘 이해하려면 43 페이지의 Ecma-Script spec pdf 를여십시오. "문자열 유형에 적용된 ToNumber"

문자열에 숫자 구문이 있고, 공백 문자를 포함 할 수있는 경우 숫자 형식으로 변환 할 수 있습니다. 빈 문자열은 0으로 평가됩니다. 또한 문자열 '무한대'는

isNaN('Infinity'); // false

13

다음을 사용하십시오.

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

또는

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

3
안녕하세요 선생님, isNaN (parseInt ( "123a")) : 123을 반환하므로 문자열에 aplha 숫자가 포함 된 경우 ur 솔루션이 작동하지 않습니다
Sajjad Ali Khan

6

에서 MDN이 문제에 대한 이유 당신이 직면하고있다

isNaN 함수의 인수가 Number 유형이 아닌 경우 값은 먼저 Number로 강제됩니다. 그런 다음 결과 값을 테스트하여 값이 NaN인지 확인합니다.

평등에 대한 NaN 비교를 다루는 다음의 포괄적 인 답변을 확인하고 싶을 수도 있습니다.

JavaScript 변수가 있는지 테스트하는 방법 NaN


5

: 나는 그것 때문에 자바 스크립트의 입력하는 생각 ' '제로로 변환되고, 반면 'x'되지 않습니다 :

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

4

정확한 isNumber 함수를 구현하려는 경우 다음은 Javascript 에서 수행하는 한 가지 방법입니다 . Douglas Crockford 의 좋은 부분 [페이지 105]

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

4
@Xyan이 경우이 함수는 OP가 요청한 작업을 수행하는 데 도움이되지 않습니다. 이는 숫자의 문자열 표현을 검사하는 것입니다.
ErikE

"숫자"와 같은 문자열 리터럴에 대해 주어진 값의 소위 완전 항등 연산자를 사용하는 것은 어리석은 일입니다.
Bekim Bacaj

4

완전하지 않은 정답

안토니오 헤일리 높은지지와 대답 은이 프로세스가 JavaScript의 parseInt기능을 수행한다고 잘못 가정 합니다.

문자열에 parseInt를 사용할 수 있습니다. 결과는 실패합니다.

이 문장을 문자열로 쉽게 반증 할 수 있습니다. "123abc" .

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

이를 통해 JavaScript의 parseInt함수가 "123abc"숫자로 반환 되는 것을 볼 수 123있지만 그 isNaN함수는"123abc" 숫자 가 아니라고 .

정답

ECMAScript-262는 섹션 18.2.3isNaN 에서 점검이 작동 하는 방식을 정의합니다 .

18.2.3 isNaN (번호)

isNaN함수는 %isNaN%고유 객체입니다. 때 isNaN함수가 하나 개의 인자 번호로 호출, 다음 단계가 수행됩니다

  1. 하자 num? ToNumber(number).
  2. 인 경우 numNaN반환하십시오 true.
  3. 그렇지 않으면를 반환하십시오 false.

ToNumber함수가 참조 하는 기능은 ECMAScript-262의 섹션 7.1.3 있습니다. 여기에서는 JavaScript가이 함수에 전달 된 문자열을 처리하는 방법에 대해 설명합니다.

질문에 주어진 첫 번째 예는 공백 문자 만 포함하는 문자열입니다. 이 섹션에서는 다음을 설명합니다.

StringNumericLiteral비어 있거나 공백 만 포함으로 변환됩니다 +0.

따라서 " "예제 문자열은+0 숫자 .

같은 섹션에도 다음과 같이 명시되어 있습니다.

문법에서을 String확장으로 해석 할 수없는 경우 StringNumericLiteral결과는 ToNumber입니다 NaN.

해당 섹션에 포함 된 모든 검사를 인용하지 않으면 " x"질문에 제공된 예제는로 해석 될 수 없으므로 위의 조건에 해당합니다 StringNumericLiteral. " x"따라서로 변환됩니다 NaN.


2

왜 그런지 잘 모르겠지만 문제를 해결하기 위해 항상 공백을 다듬기 전에 확인할 수 있습니다. 어쨌든 그렇게하고 싶을 것입니다.


4
잘린 빈 문자열도 isNaN 테스트에 실패합니다.
Egemenk

2

이 함수 isNaN("")문자열 대 숫자 유형 강제 변환 수행합니다.

ECMAScript 3-5는 typeof 연산자에 대해 다음과 같은 반환 값을 정의합니다.

  • 찾으시는 주소가 없습니다
  • 객체 (널, 객체, 배열)
  • 부울
  • 번호
  • 함수

함수 본문에서 테스트를 감싸는 것이 좋습니다.

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

이 함수는 변수 유형 을 테스트하기위한 것이 아니라 강제 값을 테스트합니다 . 예를 들어, 부울과 문자열은 숫자로 강제 변환되므로이 함수를 다음과 같이 호출 할 수 있습니다.isNumberCoerced()

stringnumber 이외의 유형 을 테스트 할 필요가없는 경우 다음 스 니펫이 일부 조건의 일부로 사용될 수 있습니다.

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

1

정수인지 여부를 제대로 확인하려면 다음 함수를 사용하는 것이 좋습니다.

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

1

isNaN(" ")거짓은 혼란스러운 행동의 일부입니다isNaN , 숫자가 아닌 숫자로의 강제 변환으로 인해 전역 함수 .

에서 MDN :

가장 초기 버전의 isNaN함수 스펙 이후, 숫자가 아닌 인수에 대한 동작은 혼동되었습니다. isNaN함수 의 인수가 Number 유형이 아닌 경우 값은 먼저 Number로 강제됩니다. 그런 다음 결과 값을 테스트하여 값이되는지 확인합니다 NaN. 따라서 숫자가 아닌 숫자의 경우 숫자 유형으로 강제 변환 될 때 유효한 비 NaN 숫자 값 (특히 빈 문자열 및 부울 기본 요소, 강제로 숫자가 0 또는 1을 제공함)을 초래하는 경우 "거짓"리턴 값은 예상치 못한 결과 일 수 있습니다. 예를 들어, 빈 문자열은 반드시 "숫자가 아님"입니다.

ECMAScript 6에는 이제 Number.isNaNMDN에 따른 방법 도 있습니다 .

전역 isNaN()함수와 비교 Number.isNaN()하여 매개 변수를 숫자로 강제 변환하는 문제가 발생하지 않습니다. 이는 일반적으로로 변환 NaN되지만 실제로는 같은 값이 아닌 값을 전달하는 것이 안전하다는 것을 의미합니다 NaN. 이는 또한 유형 번호의 값, 즉 NaN, return 만을 의미합니다 true.

불행히도 :

ECMAScript 6 Number.isNaN방법 조차도 블로그 포스트- 추악한 JavaScript 및 ES6 NaN 문제 해결에 요약 된대로 자체 문제가 있습니다 .


1

isNaN함수는 숫자를 인수로 예상하므로 실제 함수 논리가 수행 되기 전에 다른 유형 (문자열의 경우)의 인수가 숫자로 변환됩니다 . ( NaN또한 Number 유형의 값이기도합니다!)

Btw. 이것은 모든 내장 함수에 공통 입니다. 특정 유형의 인수를 예상하면 실제 인수는 표준 변환 함수를 사용하여 변환됩니다. 모든 기본 유형 (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


1

이 문제를 해결하는 데 도움이되는이 작은 기능을 작성했습니다.

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

숫자 (0-9)가 아니고 '-'또는 '.'이 아니며 정의되지 않거나 null 또는 비어 있지 않은 문자가 있는지 확인하고 일치하는 항목이 없으면 true를 반환합니다. :)


뒤늦은 당신이 이것에 감사합니다; 이것은 내 문제를 아주 잘 해결했습니다.
헨리

1

다른 설명대로 isNaN함수는 유효성을 검사하기 전에 빈 문자열을 숫자로 강제 변환하여 빈 문자열을 0 (유효한 숫자)으로 변경합니다. 그러나 빈 문자열이나 공백 만있는 문자열을 구문 분석하려고 하면 parseInt함수가 반환 된다는 것을 알았습니다 NaN. 따라서 다음 조합이 잘 작동하는 것 같습니다.

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

이 검사는 양수, 음수 및 소수점이있는 숫자에 대해 작동하므로 모든 일반적인 숫자 경우를 포함한다고 생각합니다.


1

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먼저 값을 숫자 값으로 변환해야합니다.


0

이 기능은 내 테스트에서 작동하는 것 같습니다

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

2
전체 기능을 작성할 수 있습니다.return !(s === "" || s === null || parseInt(s) == 'NaN');
ErikE

0

이건 어떤가요

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

0

자바 스크립트가 내장 된 때는 isNaN의 기능이다 - 기본적으로 예상해야으로 -는 "동적 타입 연산자". 따라서 (DTC 프로세스 중) 모든 값은 단순한 참 | 와 같은 false "", " ", " 000"는 NaN 일 수 없습니다.

것을 의미 인수 공급 먼저 받게 될 것이다 변환을 같이 :

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

설명:

함수 본문의 맨 윗줄에서, 먼저 인수를 숫자 객체로 변환하려고합니다. 그리고 둘째, 도트 연산자를 사용하여 우리 자신의 편의 를 위해 생성 된 객체 기본 을 즉시 제거 합니다.

두 번째 줄에서 우리는 이전 단계에서 얻은 가치와 NaN 이 우주의 어떤 것과도 같지 않다는 사실의 장점을 취합니다 .NaN == NaN >> false 마지막으로 (불평등에 대한) 비교에 자체 .

이 방법으로, 제공된 인수 반환이 숫자 객체, 즉 숫자가 아닌 숫자로의 변환에 실패한 경우에만 함수 리턴이 참이 됩니다. 예를 들어, NaN.


isNaNstatic ()

그러나 정적 유형 연산자의 경우 (필요한 경우) 필요한 경우 다음과 같이 훨씬 간단한 함수를 작성할 수 있습니다.

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

그리고 인수가 명시 적으로 NaN 숫자가 아닌 경우 거짓을 반환하도록 DTC를 모두 피하십시오. 따라서 다음에 대해 테스트하십시오.

isNaNStatic(" x"); // will return false 여전히 문자열이기 때문에.

그러나 : isNaNStatic(1/"x"); // will of course return true.예를 들어isNaNStatic(NaN); >> true .

그러나 (반박)이 일반 문자열이기 때문에 isNaN와 반대로 isNaNStatic("NaN"); >> false.

ps : isNaN의 정적 버전은 최신 코딩 시나리오에서 매우 유용 할 수 있습니다. 그리고 내가 이것을 게시하는 데 시간이 걸린 주요 이유 중 하나 일 수 있습니다.

문안 인사.


0

isNAN(<argument>)주어진 인수가 잘못된 숫자인지 여부를 알려주는 함수입니다. isNaN인수를 숫자 유형으로 유형 캐스트합니다. 인수가 숫자인지 여부를 확인하려면? $.isNumeric()jQuery에서 함수를 사용하십시오 .

즉, 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

0

나는 이것을 사용한다

    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


0

공백으로 특정 문자열 값 경우 확인 또는하면 " "된다 isNaN어쩌면 문자열 유효성 검사를 수행 할 예 :

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.