ParseInt (null, 24) === 23... подождите, что?

Хорошо, поэтому я возился с parseInt, чтобы увидеть, как он обрабатывает значения, еще не инициализированные, и я наткнулся на этот камень. Ниже приведено любое основание 24 или выше.

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

Я тестировал его в IE, Chrome и Firefox, и все они предупреждают об этом, поэтому я думаю, что он должен быть в спецификации где-то. Быстрый поиск в Google не дал мне никаких результатов, поэтому я здесь, надеюсь, кто-то может объяснить.

Я помню, как слушал речь Крокфорда, где он говорил typeof null === "object" из-за надзора, заставляющего Object и Null иметь идентичный идентификатор типа в памяти или что-то в этом роде, но я не могу найти это видео сейчас.

Попробуйте: http://jsfiddle.net/robert/txjwP/

Изменить. Исправление: более высокий радиус возвращает разные результаты, 32 возвращает 785077
Изменить 2 От zzzzBov: [24...30]:23, 31:714695, 32:785077, 33:859935, 34:939407, 35:1023631, 36:1112745


TL;DR

Объясните, почему parseInt(null, 24) === 23 является истинным утверждением.

Ответ 1

Преобразует 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

Ответ 2

Mozilla сообщает нам:

Функция parseInt преобразует свой первый аргумент для строки, анализирует ее и возвращает целое число или NaN. Если не NaN, возвращаемое значение будет десятичным целочисленное представление первого аргумент, взятый как число в заданный радиус (основание). Например, radix of 10 означает преобразование из десятичное число, 8 восьмеричное, 16 шестнадцатеричный и т.д. Для радиусов выше 10, буквы алфавита укажите цифры, превышающие 9. Для пример, для шестнадцатеричных чисел (базовый 16), используются A-F.

В spec, 15.1.2.2/1 сообщает нам, что преобразование в строку выполняется с использованием встроенного ToString, который (согласно 9.8) дает "null" (не путать с ToString, что даст "[object Window]"!).

Итак, рассмотрим parseInt("null", 24).

Конечно, это не числовая строка base-24 целиком, но "n": decimal 23.

Теперь разбор остановится после выталкивания десятичного числа 23, потому что "u" не найден в системе base-24:

Если S содержит любой символ, который является а не цифрой radix-R, тогда пусть Z - подстрока S, состоящая из всех символов до первого такого персонаж; в противном случае пусть Z - S. [15.1.2.2/11]

(И поэтому parseInt(null, 23) (и более низкие радиусы) дает вам NaN, а не 23: "n" не находится в системе base-23.)

Ответ 3

Игнасио Васкес-Абрамс прав, но позволяет точно видеть как это работает...

От 15.1.2.2 parseInt (string , radix):

Когда вызывается функция parseInt, выполняются следующие шаги:

  • Пусть inputString будет ToString (строка).
  • Пусть S - вновь созданная подстрока inputString, состоящая из первого характер, который не является StrWhiteSpaceChar и все символы следующий за этим характером. (В других слова, удалите ведущее белое пространство.)
  • Пусть знак равен 1.
  • Если S не пусто и первый символ S является знаком минус, пусть пусть sign be -1.
  • Если S не пусто и первый символ S является знаком плюс + или минус, а затем удалить первый символ из S.
  • Пусть R = ToInt32 (radix).
  • Пусть stripPrefix будет true.
  • Если R ≠ 0, то a. Если R < 2 или R > 36, затем верните NaN. б. Если R ≠ 16, пусть stripPrefix будет false.
  • Else, R = 0 a. Пусть R = 10.
  • Если stripPrefix истинно, то a. Если длина S не менее 2 и первые два символа S являются либо "0x" или "0X", затем удалите первый два символа из S и R = 16.
  • Если S содержит любой символ, который не является знаком radix-R, тогда пусть Z - подстрока S, состоящая из всех символов до первого такого персонаж; в противном случае пусть Z - S.
  • Если Z пуст, верните NaN.
  • Пусть mathInt - математическое целочисленное значение, которое представлено Z в нотации radix-R, используя буквы A-Z и a-z для цифр со значениями 10 через 35. (Однако, если R равно 10 и Z содержит более 20 значительных цифры, каждая значащая цифра после 20-й может быть заменен на 0 цифр, по выбору реализации; и если R не 2, 4, 8, 10, 16 или 32, то mathInt может быть зависящее от реализации приближение к математическому целочисленному значению, которое представлен Z в radix-R обозначения.)
  • Пусть number - значение Number для mathInt.
  • Возвращаемый знак × номер.

ПРИМЕЧАНИЕ. parseInt может интерпретировать только ведущая часть строки как целочисленное значение; он игнорирует любые символы, которые нельзя интерпретировать как часть обозначения целого числа, и не указывается, что любые такие символы были проигнорированы.

Здесь есть две важные части. Я смел их обоих. Итак, прежде всего, мы должны выяснить, что такое toString представление null. Нам нужно посмотреть Table 13 — ToString Conversions в разделе 9.8.0 для этой информации:

enter image description here

Отлично, теперь мы знаем, что выполнение toString(null) внутренне дает строку 'null'. Отлично, но как именно он обрабатывает цифры (символы), которые недопустимы в предоставленном radix?

Мы смотрим выше на 15.1.2.2 и видим следующее замечание:

Если S содержит любой символ, который является а не цифрой radix-R, тогда пусть Z - подстрока S, состоящая из всех символов до первого такого персонаж; в противном случае пусть Z - S.

Это означает, что мы обрабатываем все цифры PRIOR указанному основанию и игнорируем все остальное.

В принципе, выполнение parseInt(null, 23) - это то же самое, что и parseInt('null', 23). u вызывает игнорирование двух l (хотя они являются частью основания 23). Поэтому мы можем только разобрать n, делая синтаксис всего синтаксиса parseInt('n', 23).:)

В любом случае, большой вопрос!

Ответ 4

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.

В описании языка указано

  • Если S содержит любой символ, который не является цифрой radix-R, тогда пусть Z - подстрока S, состоящая из всех символов до первого такого символа; в противном случае пусть Z - S.

который является частью, обеспечивающей правильное синтаксическое определение целочисленных литералов типа C, например 15L поэтому приведенное выше эквивалентно

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

"n" является 23-й буквой списка цифр выше.

Q.E.D.

Ответ 5

Я думаю, null преобразуется в строку "null". Итак, n на самом деле 23 в 'base24' (то же самое в 'base25' +), u недопустимо в 'base24', поэтому остальная часть строки null будет проигнорирована. Поэтому он выводит 23, пока u не станет действительным в 'base31'.

Ответ 6

parseInt использует буквенно-цифровое представление, тогда в base-24 "n" действительно, но "u" является недопустимым символом, тогда parseInt только анализирует значение "n"....

parseInt("n",24) -> 23

попробуйте с этим:

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

Результат будет "3".