2014-09-24 3 views
27

오늘 자바 스크립트에서 이상하게 보였습니다. 필자는 16 진수가 아닌 16 진수 문자열을 base가 16 인 parseInt 함수에 전달했습니다. 결과가 나타납니다. 함수가 어떤 종류의 예외를 던지거나 최소한 NaN을 반환 할 것으로 기대하지만 구문 분석에 성공하여 int를 반환했습니다.parseInt ('dsff66', 16)가 13을 반환하는 이유는 무엇입니까?

내 전화했다 :

var parsed = parseInt('dsff66', 16); // note the 's' in the first argument 
 
document.write(parsed);

및 결과였다 13.

두 번째 인수에 지정된 숫자 시스템에 속하지 않는 첫 번째 문자로 "구문 분석을 중단합니다"라는 메시지가 표시되어 parseInt('fg',16)을 호출하면 결과적으로 15이 표시됩니다.

내 의견으로는 NaN이 반환됩니다. 아무도 왜 내게 설명 할 수 있습니까? 왜 누군가는이 함수가 (문자열이 전달 된 정확한 표현이 아니더라도 정수를 반환하는) 동작을 원하겠습니까?

+8

주 당신이에서는 parseInt'처럼 뭔가를 할 경우 ("2foo을", 10) '당신은'2'를 얻는다. 이것은 예상대로입니다. 그것은 첫 번째 비 숫자 문자를 구문 분석 –

+35

* 내 생각에, 그것은 NaN을 반환해야합니다. 아무도 왜 내게 설명 할 수 있겠습니까? 불행히도 제 의견이나 본인의 의견은 중요하지 않습니다. –

+14

'parseInt가 지정된 기수에서 숫자가 아닌 문자를 만날 경우, 그 문자와 모든 이어지는 문자를 무시하고 그 점까지 구문 분석 된 정수 값을 반환합니다.'source : https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Global_Objects/parseInt –

답변

22

왜 사람이 기능은 (이 같은 행동 정수를 반환 할 것입니다 직접보기 전달 된 문자열의 표현)?

때문에 당신은 기본 10 개 숫자 노력하고 있으며,이 경우 JS는 캐스트 단지 수 있습니다 (지금까지) 대부분의 시간 - 구문 분석하지 - 문자열을 숫자로.

JS는 동적으로 입력되므로 일부 문자열은 사용자의 작업없이 숫자로만 작동합니다. 예를 들어 :

"21"/3; // => 7 
"12.4"/4; // => 3.1 

parseInt 필요 없음, 때문에 "21""12.4" 숫자는 이미 본질적으로. 문자열이 "12.4xyz" 인 경우 나눌 때 실제로는 NaN이됩니다. 이는 숫자가 아니며 암시 적으로 캐스트되거나 강요 될 수 없기 때문입니다.

Number(someString)으로 숫자에 문자열을 명시 적으로 "캐스팅"할 수도 있습니다. 너무 기본 10을 지원하는 동안 실제로 유효하지 않은 문자열에 대해 NaN을 반환합니다.

그래서 JS에는 이미 암시 적/명시 적 유형의 형 변환/변환이 있기 때문에 parseInt의 역할은 아직 다른 유형의 형변환 함수가 아닙니다.

parseInt의 역할은 대신 구문 분석 기능입니다. 입력 내용을 이해하고 가능한 한 반환하기 위해 최선을 다하는 함수. 그것은 당신이 문자열을 가지고있을 때를위한 것입니다. 은 단지 완벽하지 않은 숫자이기 때문에 단지 캐스팅 할 수 없습니다.. (JS의 기본 문법과 마찬가지로, Apsillers의 대답이 멋지게 설명 된 것처럼 C를 연상케합니다.)

캐스팅 기능이 아닌 파서이기 때문에 10보다 다른베이스를 처리 할 수있는 추가 기능이 있습니다. . 이제

, 당신은 안녕, 그냥하지 않습니다 ... 비 밑이 10 인 숫자를 처리하는 엄격한 캐스팅 기능이없는 이유를 요청할 수 있습니다, 그리고 당신이 원하는처럼 불평,하지만. JS의 설계자는 parseInt으로 충분할 것이라고 결정했습니다. 다시 0x63 %의 시간 동안 10 진수를 처리하기 때문입니다.

var hexString = "dsff66"; 
var number = eval("0x" + hexString); // attempt to interpret as a hexadecimal literal 

0xdsff66 리터럴 유효한 진수가 아닌 SyntaxError 때문에 던져 which'll :

는 "캐스팅"을 얻을 수있는 가장 가까운 아마 같은 끔찍하게 해키 무언가이다.

업데이트 : Lekensteyn이 코멘트에서 지적 하듯이, JS가 나타납니다 제대로 너무 0x -prefixed 진수 문자열을 캐스팅합니다. 나는 이것을 몰랐다, 그러나 실제로이 작동하는 것 같다 : 그것은 숫자에 16 진수 문자열을 캐스팅하는 가장 간단한 방법하게

1 * "0xd0ff66"; // => 13696870 
1 * "0xdsff66"; // => NaN 

- 그리고 제대로 표시 할 수없는 경우 NaN를 얻을.

동일한 동작은 Number()에 적용됩니다. 예를 들어 Number("0xd0ff66")은 정수를 반환하고 Number("0xdsff66")NaN을 반환합니다.

(/업데이트) 또는

, 당신은 문자열을 사전에 확인하고 필요한 경우 NaN를 반환 할 수 있습니다

function hexToNumber(string) { 
    if(!/^(0x)?[0-9a-f]+$/i.test(string)) return Number.NaN; 
    return parseInt(string, 16); 
} 
+5

Ew,'eval'. 문자열을 숫자로 "캐스팅"하면 비슷한 효과를 얻을 수 있습니다. '1 * "0xdsff66"'적어도 Firefox에서는''NaN''을 제공합니다. 이것이 사양에 맞는지 확인하는 것은 독자의 연습입니다. – Lekensteyn

+0

@Lekensteyn 예, 네. 나는 그것이 끔찍한 것이라고 말했다. 그러나 재미있는'0x'-prefixed string 역시 캐스팅되었다. Chrome에서도 잘 작동합니다. – Flambino

+0

글쎄, 그건 좋은 설명 :) 둘 다 감사합니다. –

43

parseInt은 유효하지 않은 문자를 만날 때까지 입력을 읽은 다음 유효하지 않은 문자 이전에 읽은 유효한 입력을 사용합니다. 고려 :

parseInt("17days", 10); 

이 입력 17을 사용하고 유효하지 않은 d 후 모든 것을 생략합니다. 가입일

ECMAScript specification :

[입력 문자열] S는 기수 R 숫자가 아닌 임의의 문자를 포함하는 경우, Z [문자열 정수 ified하게되도록]하자 S의 문자열 될 첫 번째 문자 앞에있는 모든 문자로 구성; 그렇지 않으면, Z는 사용자의 예에서

S.

하자, s 잘못된 기본-16 문자, 그래서 parseInt은 최고의 d을 사용합니다. 에 대한

으로는이 동작이 포함 된 이유 :이 확실히 알 수있는 방법은 없습니다, 그러나 이것은 매우 가능성이 C의 표준 라이브러리에서 (긴 문자열로) strtol의 동작을 재현하는 시도이다. strtol(3) man page에서 :

... 문자열은 이 주어진 기본의 유효 숫자가 아닌 첫 번째 문자에서 중지, 명백한 방식으로 긴 int 값으로 변환됩니다.

이 연결

parseIntstrtol 모두 공백을 선도 무시하도록 지정되어 있다는 사실 (어느 정도) 지원, 그들은 모두 진수 값에 대한 선도적 인 0x을 받아 들일 수 있습니다. 당신의 문자열 dsff66에서

+0

+1 스펙을 참조하십시오. – Robert

6

For radices above 10, the letters of the alphabet indicate numerals greater than 9. For example, for hexadecimal numbers (base 16), A through F are used.

d는 기수 유형을 맞는 수 13에 해당하는 진수 문자 (문자열이 아닌 진수 경우에도)입니다.그것은 다음 문자가 16 진수가 아니기 때문에 구문 분석을 중지합니다.

12

이 경우에 parseInt()"A"에서 "F"까지의 문자를 해석하여 hexadecimal으로하고 10 진수로 해석하십시오. 즉 d13을 반환합니다.

무엇으로 parseInt()는

  • parseInt("string", radix)이 수에 (이 기수에 따라) 진수로 문자열에서 숫자와 문자를 해석한다.

  • parseInt() 문자열의 시작부터 유효하지 않은 문자가 16 진수가 될 때까지 16 진수로만 구문 분석 숫자 또는 문자를 구문 분석하십시오.

  • parseInt() 경우 NaN이를 반환 문자열 parseInt()의 시작 부분에 숫자 또는 16 진수로 편지를 찾을 수 없습니다.

  • 기수가 정의되지 않은 경우 기수는 10입니다.

  • 문자열이 "0x"으로 시작하는 경우 기수는 16입니다.

  • radix가 0으로 정의 된 경우 기수는 10입니다.

  • 기수가 1 인 경우 parseInt()은 NaN입니다.

  • 기수가 2 경우

    , parseInt()"0""1" 구문 분석합니다.

  • 기수 3,으로 parseInt()의 경우에만 "0", "1""2" 파싱. 등등. 0

  • parseInt() 파싱 "0"에는 번호가 결과로 다음없고 개수가이를 뒤 따르는 경우 0 제거가있는 경우. 예 : "0"반환 0 "01"반환 1.

  • 기수가 11 경우, "0"에서 "9" 및/또는 편지 "A"에 숫자로 시작 parseInt()에만 구문 분석 문자열입니다. 기수가 12 경우

  • ,에서는 parseInt는 "0"에서 등등 "9" 및/또는 편지 "A""B", 그리고에 숫자로 시작 문자열을 구문 분석합니다.

  • 최대 기수는 36, 그것은 "0""Z"-"A"에서 "9" 및/또는 문자에 숫자로 시작 문자열을 구문 분석 것이다.

  • 문자가 16 진수로 여러 개 해석되는 경우 모든 문자의 값은 같지만 문자는 같습니다. 예 : parseInt("AA", 11) 첫 번째 "A"은 두 번째와 다른 값을 갖습니다. "A".

  • 문자열이 같은 문자열이지만 다른 기수가 다른 숫자를 반환합니다.

는 정확한없는 경우에도

document.body.innerHTML = "<b>What parseInt() does</b><br>" + 
 
          "parseInt('9') = " + parseInt('9') + "<br>" + 
 
          "parseInt('0129ABZ', 0) = " + parseInt('0129ABZ', 0) + "<br>" + 
 
          "parseInt('0', 1) = " + parseInt('0', 1) + "<br>" + 
 
          "parseInt('0', 2) = " + parseInt('0', 2) + "<br>" + 
 
          "parseInt('10', 2) = " + parseInt('10', 2) + "<br>" + 
 
          "parseInt('01', 2) = " + parseInt('01', 2) + "<br>" + 
 
          "parseInt('1', 2) = " + parseInt('1', 2) + "<br>" + 
 
          "parseInt('A', 10) = " + parseInt('A', 10) + "<br>" + 
 
          "parseInt('A', 11) = " + parseInt('A', 11) + "<br>" + 
 
          "parseInt('Z', 36) = " + parseInt('Z', 36) + "<br><br>" + 
 
          "<b>The value:</b><br>" + 
 
          "parseInt('A', 11) = " + parseInt('A', 11) + "<br>" + 
 
          "parseInt('A', 12) = " + parseInt('A', 12) + "<br>" + 
 
          "parseInt('A', 13) = " + parseInt('A', 13) + "<br>" + 
 
          "parseInt('AA', 11) = " + parseInt('AA', 11) + " = 100 + 20" + "<br>" + 
 
          "parseInt('AA', 12) = " + parseInt('AA', 12) + " = 100 + 30" + "<br>" + 
 
          "parseInt('AA', 13) = " + parseInt('AA', 13) + " = 100 + 40" + "<br>" + 
 
          "parseInt('AAA', 11) = " + parseInt('AAA', 11) + " = 1000 + 300 + 30" + "<br>" + 
 
          "parseInt('AAA', 12) = " + parseInt('AAA', 12) + " = 1000 + 500 + 70" + "<br>" + 
 
          "parseInt('AAA', 13) = " + parseInt('AAA', 13) + " = 1000 + 700 + 130" + "<br>" + 
 
          "parseInt('AAA', 14) = " + parseInt('AAA', 14) + " = 1000 + 900 + 210" + "<br>" + 
 
          "parseInt('AAA', 15) = " + parseInt('AAA', 15) + " = 1000 + 1100 + 310";

+1

'기수가 정의되지 않은 경우 기수는 10입니다 .' - 일반적으로 true이지만 이전 브라우저의 기본값은 기수가 8 일 수 있습니다. [parseInt at MDN] (https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Global_Objects/parseInt). –