Подтвердить что ты не робот

Получение NaN несогласованного отображения parseInt

Играла с некоторым кодом для создания массива 0 и обнаружила, что вместо 0 было возвращено только одно значение NaN. Я получаю это в Chrome, Node и Firefox.

Что вызывает второе значение NaN?

var arr = new Array(32).join(0).split('').map(parseInt)
// prints [0, NaN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
console.dir(arr)
4b9b3361

Ответ 1

Это потому, что функция, переданная в map, будет вызываться с тремя аргументами:

  • Текущий элемент массива
  • Индекс этого элемента
  • Весь массив

В этом случае эта функция parseInt, которая использует только два аргумента:

  • Строка, подлежащая анализу
  • Радикс, используемый для синтаксического анализа строки
  • Дополнительные аргументы будут проигнорированы.

Следовательно, для второго элемента в массиве (т.е. index 1) вызов будет

parseInt("0", 1, ignoredArray)

Когда радиус 1, возвращается NaN:

  • Пусть R = ToInt32 (radix).
  • Если R ≠ 0, то
    • Если R < 2 или R > 36, затем верните NaN.

Также обратите внимание, что если вы использовали большее число, например new Array(99), вы бы увидели NaN, начиная с индекса 37.

Ответ 2

Функция .map() передает три аргументы обратного вызова, из которых два используются parseInt(): значение и индекс (третий - сам массив). Когда индекс 1, любая строка цифр будет недопустимым значением. Функция parseInt() игнорирует второй аргумент, когда он 0.

Чтобы разработать: для первого элемента parseInt() вызывается так:

parseInt("0", 0)

потому что значение массива равно нулю, а индекс равен нулю. Во втором вызове это:

parseInt("0", 1)

и возвращает NaN.

Обратите внимание: если вы не слишком придирчивы к тому, что результаты являются целыми, вы можете делать то, что вы пытаетесь сделать с конструктором Number:

var arr = new Array(32).join(0).split('').map(Number);

В ES2015 (самый новый ратифицированный стандарт для JavaScript, который, если мы все очень хорошо, будет полностью реализован во всех браузерах в качестве рождественского подарка), вы можете использовать функцию .fill():

var arr = new Array(31).fill(0);

Ответ 3

Отображение передает три аргумента своей функции:

  • элемент;
  • индекс этого элемента в массиве; и
  • сам массив.

Функция parseInt будет смотреть на первые две из них, обрабатывая первое правильно как строку, но обрабатывая вторую как базу для использования. Когда база не равна ни нулю, ни во включенном диапазоне 2..36, она возвращает NaN (1). Если у вас есть массив со сорока элементами, вы также увидите кучу значений NaN в конце:

0, NaN, 0, 0, 0, ... 0, 0, 0, NaN, NaN

Вы также получите некоторые довольно странные результаты, если числовые строки были чем-то иным, кроме нуля, так как индекс массива определял бы, какая база была использована для его интерпретации.

Чтобы на самом деле исправить, вы можете просто предоставить функцию, которая будет транслировать то, что map дает вам то, что ожидает parseInt (карта карты, я думаю, вы могли бы ее назвать):

function myParseInt(s,r,a) { return parseInt(s,10); }
var arr = new Array(32).join(0).split('').map(myParseInt)
alert(arr)

Вы также можете посмотреть, как вы создаете этот массив, на самом деле он окажется в виде массива размером 31, а не 32. Если вам нужен массив из '0' символов, вы можете просто используйте:

var arr = new Array(32).fill('0')

предполагая, что у вас есть браузер, который поддерживает ECMAScript 2015, который является Safari, Firefox и Chrome-desktop со времени ответа.


(1) Базой нуля является случай по умолчанию для обработки таких вещей, как шестнадцатеричные префиксы.

База одного не имеет смысла в чисто позиционной системе (где каждая цифра умножается на мощность базы и накапливается), так как только разрешенная цифра будет 0, поэтому каждое значение места будет равным нулю умноженное на 1n. Другими словами, единственное возможное число в системе base-one будет равно нулю.

Основания от 2 до 36, следовательно, более разумны.