Джаваскрипт странный. не доверяют мне? Попробуйте использовать map и parseInt для преобразования массива строк в целое число. Запустите консоль (F12 в Chrome), вставьте следующее и нажмите Enter.Перевести
оригинальныйmedium.com/dailyjs
['1', '7', '11'].map(parseInt);
В итоге мы получаем не массив целых чисел, например [1, 7, 11], а массив длинных чисел, например [1, NaN, 3] . Чтобы понять, что происходит, мы сначала обсудим некоторые концепции Javascript. Если вам нужна сводка (TLDR), я включил краткую сводку в конце этой истории.
Правда и ложь
Вот простой оператор if-else в Javascript:
if (true) {
// 永远都会运行
} else {
// 永远不会运行
}
В этом случае условие оператора if-else истинно, поэтому блок операторов if-block всегда выполняется, а блок операторов else-block игнорируется. Это простой пример, потому что true — логическое значение. Что, если мы сделаем нелогическое значение условием?
if ("hello world") {
// 他会运行吗?
console.log("Condition is truthy");
} else {
// 还是运行这个?
console.log("Condition is falsy");
}
Попробуйте запустить этот код в консоли браузера (F12 в Chrome). Вы должны обнаружить, что блок операторов if-block работает. Это связано с тем, что строковый объект "hello world" является истинным.
Каждый объект Javascript является либо истинным, либо ложным при помещении в логический контекст. Например, операторы if-else будут преобразовывать объекты Javascript в true или false. Итак, какие объекты истинны, а какие ложны? Вот простое правило:
Javascript возвращает false, когда следующие значения помещаются в логический контекст
false, 0 ("" пустая строка), null, undefined и NaN.
база (база)
0 1 2 3 4 5 6 7 8 9 10
Когда мы считаем от 0 до 9, каждое число (0-9) имеет свой знак. Однако, как только мы достигнем 10, нам понадобятся два разных символа (1 и 0) для представления числа. Это потому, что основание (или основание) нашей десятичной системы счисления равно 10.
Основание — это наименьшее число, которое может быть представлено только несколькими символами. Разные системы счета имеют разные основания, поэтому одно и то же число может относиться к разным числам в системе счета.
10进制 二进制 16进制
0 0 0
1 1 1
2 10 2
3 11 3
4 100 4
5 101 5
6 110 6
7 111 7
8 1000 8
9 1001 9
10 1010 A
11 1011 B
12 1100 C
13 1101 D
14 1110 E
15 1111 F
16 10000 10
17 10001 11
Например, глядя на таблицу выше, мы видим, что одно и то же число 11 может обозначать разные числа в разных системах счета. Если основание (основание) равно 2, значит число 3. Если основание (основание) равно 16, значит число 17.
Вы могли заметить, что в нашем примере, когда на входе 11, parseInt возвращает 3, что соответствует двоичному столбцу в таблице выше.
параметр функции
Функции в Javascript можно вызывать с любым количеством аргументов, даже если они не равны количеству объявленных аргументов функции. Отсутствующие параметры рассматриваются как неопределенные, а избыточные параметры игнорируются (но сохраняются в объекте параметров, подобном массиву).
function foo(x, y) {
console.log(x);
console.log(y);
}
foo(1, 2); // logs 1, 2
foo(1); // logs 1, undefined
foo(1, 2, 3); // logs 1, 2
функция карты()
Мы почти на месте!
Map — это метод в прототипе Array, который возвращает новый массив с результатом передачи каждого элемента исходного массива в функцию. Например, следующий код умножает каждый элемент массива на 3.
function multiplyBy3(x) {
return x * 3;
}
const result = [1, 2, 3, 4, 5].map(multiplyBy3);
console.log(result); // logs [3, 6, 9, 12, 15];
Теперь предположим, что я хочу регистрировать каждый элемент с помощью map() (без оператора return). Я должен иметь возможность использовать console.log в качестве аргумента для map()...
[1,2,3,4,5] .map(console.log);
Происходят очень странные вещи. Каждый вызов console.log регистрирует индекс и полный массив, а не только значение.
[1, 2, 3, 4, 5].map(console.log);
// 上面的例子相当于
[1, 2, 3, 4, 5].map(
(val, index, array) => console.log(val, index, array)
);
// 而不是这样
[1, 2, 3, 4, 5].map(
val => console.log(val)
);
Когда функция передается в map(), для каждой итерации функции передаются три аргумента: currentValue, currentIndex и полный массив. Вот почему за каждую итерацию записываются три записи.
Теперь у нас есть все детали, необходимые для разгадки этой тайны.
разгадать тайну
ParseInt имеет два параметра: строку и систему счисления (основание). Если предоставленная система счисления (база) пуста или ложна, по умолчанию база (база) устанавливается равной 10.
parseInt('11'); => 11
parseInt('11', 2); => 3
parseInt('11', 16); => 17
parseInt('11', undefined); => 11 (radix(进制) 为假)
parseInt('11', 0); => 11 (radix(进制) 为假)
Теперь давайте запустим наш пример шаг за шагом.
['1', '7', '11'].map(parseInt); => [1, NaN, 3]
// 第一次迭代: val = '1', index = 0, array = ['1', '7', '11']
parseInt('1', 0, ['1', '7', '11']); => 1
Поскольку 0 является ложным, база (база) устанавливается на значение по умолчанию 10. parseInt() принимает только два аргумента, поэтому ['1', '7', '11'] будут игнорироваться. Строка «1» в базе 10 (основание) представляет число 1.
// 第二次迭代: val = '7', index = 1, array = ['1', '7', '11']
parseInt('7', 1, ['1', '7', '11']); => NaN
В базовой (базовой) 1 системе символа «7» не существует. Как и в первой итерации, последний параметр игнорируется. Итак, parseInt() вернул NaN.
// 第三次迭代: val = '11', index = 2, array = ['1', '7', '11']
parseInt('11', 2, ['1', '7', '11']); => 3
В базовой (базовой) 2 (двоичной) системе символ «11» представляет число 3, а последний аргумент игнорируется.
Аннотация (TLDR)
['1', '7', '11'].map(parseInt) не работает должным образом, потому что map передает три аргумента в функцию parseInt() на каждой итерации. Второй параметр, index, передается в parseInt как параметр системы счисления (шестнадцатеричный). Поэтому каждая строка в массиве анализируется с использованием другой базы (базы). «7» анализируется как база (база) 1, которая является NaN, «11» анализируется как база (база) 2, ее значение равно 3, а «1» анализируется как база по умолчанию (база) ) равна 10, потому что его индекс 0 является ложным.
Я не знаю, все ли вы понимаете