parseInt (null, 24) === 23… 잠깐만 요?


226

좋아, 그래서 parseInt로 엉망이되어 아직 초기화되지 않은 값을 처리하는 방법을 보았고이 보석을 발견했습니다. 기수 24 이상에서는 다음이 발생합니다.

parseInt(null, 24) === 23 // evaluates to true

IE, Chrome 및 Firefox에서 테스트했으며 모두 사실임을 알리므로 어딘가에 사양에 있어야한다고 생각합니다. 빠른 Google 검색으로 결과가 나오지 않아 누군가가 설명 할 수 있기를 바랍니다.

typeof null === "object"Object와 Null이 메모리 또는 그 라인을 따라 비슷한 유형 식별자를 갖도록 감독하는 감독 때문에 Crockford 연설 을들은 것을 기억하지만 지금은 그 비디오를 찾을 수 없습니다.

사용해보십시오 : http://jsfiddle.net/robert/txjwP/

수정 수정 : 기수가 높을수록 다른 결과가, 32가 반환됩니다. 785077 zzzzBov에서
편집 2 :[24...30]:23, 31:714695, 32:785077, 33:859935, 34:939407, 35:1023631, 36:1112745


tl; dr

parseInt(null, 24) === 23진실한 진술 인지 설명하십시오 .


49
기발한. JavaScript는 항상 당신을 발가락에 유지합니다.
FishBasketGordo

1
데이터 포인트 : alert(parseInt(null, 34) === 23)생산false
Stephen P

1
alert(parseInt(null,26)===23);또한 진정한?!?!
Petar Ivanov

6
[24...30]:23, 31:714695, 32:785077, 33:859935, 34:939407, 35:1023631, 36:1112745,[37...]:NaN
zzzzBov

1
추가 undefined로, 첫 번째 매개 변수가 30의 홀수 결과를 리턴
하므로

답변:


240

그것은 변환있어 null문자열로 "null"및 변환하려고합니다. 기수 0-23의 경우 변환 할 수있는 숫자가 없으므로을 반환합니다 NaN. 24 "n"에서 14 번째 문자는 숫자 시스템에 추가됩니다. 31 "u"에서 21 번째 문자가 추가되고 전체 문자열을 디코딩 할 수 있습니다. 37에서 더 이상 생성 될 수있는 유효한 숫자 세트가없고 NaN이 리턴됩니다.

js> parseInt(null, 36)
1112745

>>> reduce(lambda x, y: x * 36 + y, [(string.digits + string.lowercase).index(x) for x in 'null'])
1112745

3
@ Tomalak : 누가 사용하고 있다고 말 toString()합니까?
Ignacio Vazquez-Abrams

3
@ 이그나시오. 사실, 나는 틀렸다. 나는 37이 기수를 참조하고 있다는 것을 몰랐다. 미안합니다.
Mike Samuel

3
@Robert, 아니, 나는 혼란스러워하고 그가 주장하는 것 이외의 것을 주장하고 있다고 생각했다. 정답입니다. 모든 사과.
Mike Samuel

19
나는 여전히이 대답이 일부 참고 문헌과 관련이 있다고 생각합니다. 완전히 정확하지만 실제로는 단 하나의 큰 주장입니다.
Orbit의 Lightness Races

4
@ Tomalak-모든 참조에 대한 내 대답을 확인하십시오. 이 답변은 올바른 (첫 번째) 답변이므로 받아 들여야합니다. 후드 아래에서 일어나는 일을 설명하는 것은 결코 아프지 않지만;)
David Titarenco

118

모질라가 알려줍니다 .

parseInt 함수 는 첫 번째 인수를 string으로 변환하여 구문 분석 한 후 정수 또는 NaN을 반환합니다. NaN이 아닌 경우 반환 된 값은 지정된 기수 (기본)의 숫자로 취한 첫 번째 인수의 10 진 정수 표현입니다. 예를 들어 기수 10은 10 진수, 8 진수 8 진수, 16 진수 16 진수 등으로 변환됨을 나타냅니다. 10보다 큰 복사의 경우 알파벳 문자는 9보다 큰 숫자를 나타냅니다. 예를 들어 16 진수 (기수 16)의 경우 A에서 F까지가 사용됩니다.

에서는 사양 , 15.1.2.2/1는 문자열로 변환하여 수행되는 내장 우리에게 알려줍니다 ToString(9.8에 따라) 수익률이하는 "null"(혼동하지 toString얻을 것이다, "[object Window]"!)를.

고려해 봅시다 parseInt("null", 24).

물론 24 자릿수 의 숫자 문자열은 아니지만 "n"은 10 진수 23 입니다.

이제 24 진수 시스템에서 찾을 수 "u" 없으므로 10 진수 23을 빼면 구문 분석이 중지됩니다 .

S에 기수 -R 숫자가 아닌 문자가 포함 된 경우 Z는 첫 번째 문자 앞의 모든 문자로 구성된 S의 하위 문자열이되어야합니다. 그렇지 않으면 Z를 S로하자. [15.1.2.2/11]

(그리고 이것이 23 parseInt(null, 23)NaN아닌 (그리고 더 낮은 기수)가 당신에게주는 이유입니다 : "n"base-23 시스템에 없습니다.)


2
이것은 parseInt의 비극적 인 행동입니다 (이 경우 예외로 설계되지 않은 이유를 생각하고있었습니다). 가능한 경우 NUMBER ()를 대신 사용하고 싶습니다.
Grijesh Chauhan

79

Ignacio Vazquez-Abrams는 정확하지만 작동 방식을 정확하게 볼 수 있습니다 ...

보낸 사람 15.1.2.2 parseInt (string , radix):

parseInt 함수가 호출되면 다음 단계가 수행됩니다.

  • inputString을 ToString (string)으로 설정하십시오.
  • S를 StrWhiteSpaceChar가 아닌 첫 번째 문자와 해당 문자 다음에 오는 모든 문자로 구성된 inputString의 새로 작성된 하위 문자열이되도록하십시오. 즉, 선행 공백을 제거하십시오.
  • 부호를 1로 설정하십시오.
  • S가 비어 있지 않고 S의 첫 문자가 빼기 부호 인 경우 부호는 -1이됩니다.
  • S가 비어 있지 않고 S의 첫 번째 문자가 더하기 부호 + 또는 빼기 기호 인 경우 S에서 첫 번째 문자를 제거하십시오.
  • R = ToInt32 (기수)라고하자.
  • stripPrefix를 true로 설정하십시오.
  • R ≠ 0이면 a. R <2 또는 R> 36이면 NaN을 반환하십시오. 비. R ≠ 16 인 경우 stripPrefix를 false로 설정하십시오.
  • 그렇지 않으면 R = 0입니다. R = 10이라고하자.
  • stripPrefix가 true이면 a. S의 길이가 2 이상이고 S의 처음 두 문자가“0x”또는“0X”인 경우 S에서 처음 두 문자를 제거하고 R = 16으로 둡니다.
  • S에 기수 -R 숫자가 아닌 문자가 포함 된 경우 Z는 첫 번째 문자 앞의 모든 문자로 구성된 S의 하위 문자열이되어야합니다. 그렇지 않으면 Z가 S가되게하십시오.
  • Z가 비어 있으면 NaN을 반환합니다.
  • mathInt를 10에서 35 사이의 숫자에 대해 문자 AZ 및 az를 사용하여 기수 -R 표기법으로 Z로 표시되는 수학적 정수 값으로 설정하십시오. 그러나 R이 10이고 Z가 20보다 큰 유효 숫자를 포함하는 경우 20 번째 이후의 숫자는 구현 옵션에 따라 0 숫자로 대체 될 수 있으며, R이 2, 4, 8, 10, 16 또는 32가 아닌 경우 mathInt는 수학 정수에 대한 구현 종속 근사치 일 수 있습니다. 기수 -R 표기법으로 Z로 표시되는 값)
  • 숫자를 mathInt의 숫자 값으로 설정하십시오.
  • 리턴 부호 × 숫자.

참고 parseInt는 문자열의 맨 앞 부분 만 정수 값으로 해석 할 수 있습니다. 정수 표기법의 일부로 해석 할 수없는 문자는 무시하고 해당 문자가 무시되었다는 표시는 없습니다.

여기에는 두 가지 중요한 부분이 있습니다. 나는 둘 다 굵게 표시했다. 우선, 우리는 그 toString표현이 무엇인지 찾아야합니다 null. Table 13 — ToString Conversions해당 정보에 대해서는 9.8.0 절 을 살펴 봐야 합니다.

여기에 이미지 설명을 입력하십시오

이제 toString(null)내부적으로 수행 하면 'null'문자열이 생성 됩니다. 훌륭하지만 제공된 기수 내에서 유효하지 않은 숫자 (문자)를 어떻게 정확하게 처리합니까?

우리는 위를 15.1.2.2보고 다음과 같은 말을 봅니다.

S에 기수 -R 숫자가 아닌 문자가 포함 된 경우 Z는 첫 번째 문자 앞의 모든 문자로 구성된 S의 하위 문자열이되어야합니다. 그렇지 않으면 Z가 S가되게하십시오.

즉, 지정된 기수보다 먼저 모든 자릿수를 처리하고 다른 모든 것은 무시합니다.

기본적으로하는 것은와 parseInt(null, 23)동일합니다 parseInt('null', 23). 이로 u인해 2 l가 무시됩니다 ( 두 기수 23의 일부 임에도 불구하고). 따라서 구문 분석 만 수행 할 수 n있으며 전체 구문은 동의어가됩니다 parseInt('n', 23). :)

어느 쪽이든 좋은 질문입니다!


33
parseInt( null, 24 ) === 23

에 해당

parseInt( String(null), 24 ) === 23

어느 것이

parseInt( "null", 24 ) === 23

밑 24의 자릿수는 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, ..., n입니다.

언어 사양에 따르면

  1. S에 기수 -R 숫자가 아닌 문자가 포함 된 경우 Z는 첫 번째 문자 앞의 모든 문자로 구성된 S의 하위 문자열이되어야합니다. 그렇지 않으면 Z가 S가되게하십시오.

이는 C 스타일 정수 리터럴이 15L올바르게 구문 분석되도록하는 부분이므로 위의 내용은

parseInt( "n", 24 ) === 23

"n" 위 숫자 목록의 23 번째 문자입니다.

QED


16

나는 null문자열로 변환 된다고 생각한다 "null". 따라서 n실제로 23는 'base24'( 'base25'+와 동일)에 있고 'base24' u에서는 유효하지 않으므로 나머지 문자열 null은 무시됩니다. 이것이 'base31'에서 유효해질 23때까지 출력되는 이유 u입니다.


7

parseInt는 영숫자 표현을 사용하고, 기본 24에서 "n"은 유효하지만 "u"는 유효하지 않은 문자이며 parseInt는 "n"값만 구문 분석합니다 ....

parseInt("n",24) -> 23

예를 들어 다음과 같이 시도하십시오.

alert(parseInt("3x", 24))

결과는 "3"입니다.

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