##### ['1', '2', '3'].map(parseInt) what & why?
看到这个题目,第一眼认为答案是[1, 2, 3],但实际答案却是[1, NaN, NaN]。
我们一贯的思维parseInt一般默认只有一个参数,并将其转为整数,又map方法循环操作每一个元素,并返回一个新的数组,导致认为答案是[1, 2, 3]。下面详细介绍数组的map()方法与parseInt()方法。
map()
在数组的原型上有这样一个方法:Array.prototype.map(),该方法创建一个新数组,其结果是调用该方法的数组中的每一个元素都调用一个提供的函数后返回的结果。
看一个简单的例子:
var array1 = [1, 3, 5];
const map1 = array1.map(x => x * 2);
console.log(map1);// [2, 6, 10];
[语法规则]
var new_array = arr.map(function callback(currentValue, index, array){}, thisArg);
[参数含义]
callback: 生成新数组元素的函数,可接受三个参数:
- currentValue:数组中正在处理的当前元素
- index(可选): 数组中正在处理的当前元素索引
- array(可选): map方法被调用的数组
thisArg(可选):执行callback函数时使用的this值。
[描述]
map方法会给原数组的每一个元素都按顺序调用一次callback函数。callback每次执行后的返回值,组合形成一个新的数组。
parseInt()
parseInt(string, radix)将字符串string转换为radix进制的整数,radix为介于2-36之间的数。 比如parseInt(333, 4) 表示333这个数是4进制,把这个4进制的数转为10进制输出。
看一个例子:
function roughScale(x, base) {
var parsed = parseInt(x, base);
if(isNaN(parsed)) {
return 0;
}
return parsed * 100;
}
console.log(roughScale('0xF', 16));// 1500
console.log(roughScale('321', 2));// 0
这个例子中0xF是16进制数,转为10进制数为15,所以parsed是一个数,返回15* 100 = 1500; 而321不是有效的2进制数,所以parsed不是数,返回0。
[语法规则]
parseInt(string, radix);
[参数含义]
string: 要被解析的值。如果参数不是一个字符串,则将其转换为字符串。字符串开头的空白符将会被忽略。
radix: 一个介于2和36之间的整数,表示上述字符串的基数。当未指定基数时,默认为10.
[返回值]
返回解析后的整数值。如果被解析的第一个字符无法被转为数值类型,则返回NaN。
例如:
parseInt('123', 5) // 将'123'看作5进制数,返回10进制数38 => 1*5^2 + 2*5^1 + 3*5^0
[描述]
parseInt函数将其第一个参数转换为字符串,解析它,并返回一个整数或NaN。如果不是NaN,且返回的整数是基数的有效数字,返回值为该整数对应10进制数。
如果parseInt的字符中有一个不是指定基数中的有效数字,则忽略该字符和该字符所有后续字符,并返回解析到该点的整数值。
看下面的例子:
console.log( parseInt('6.022e23', 10));// 6
console.log( (6.022e2).toString());// 602.2
console.log(parseInt(6.022e2, 10)) ;// 602
console.log(parseInt("Hello", 8)) ; // NaN
console.log(parseInt("546", 2)) ; // NaN ( 除了“0、1”外,其它数字都不是有效二进制数字)
在基数为 undefined,或者基数为 0 或者没有指定的情况下,JavaScript 作如下处理:
- 如果字符串 string 以"0x"或者"0X"开头, 则基数是16 (16进制).
- 如果字符串 string 以"0"开头, 基数是8(八进制)或者10(十进制),那么具体是哪个基数由实现环境决定。 ECMAScript 5 规定使用10,但是并不是所有的浏览器都遵循这个规定。因此,永远都要明确给出radix参数的值。
- 如果字符串 string 以其它任何值开头,则基数是10 (十进制)。
- 如果第一个字符不能被转换成数字,parseInt返回NaN。
回到实例
在了解了这两个方法之后,下面回到这个题目:
console.log(['1', '2', '3'].map(parseInt));
对于每个迭代map,parseInt()传递两个参数:字符串和基数
所以实际执行的代码是;
['1', '2', '3'].map((item, index) => {
return parseInt(item, index);
})
返回的值分别为:
parseInt('1', 0)// 1
parseInt('2', 1)// NaN
parseInt('3', 2)// NaN (3不是二进制)
所以结果如下:
['1', '2', '3'].map(parseInt)// [1, NaN, NaN];
再看一个例子:
['10', '10', '10', '10', '10'].map(parseInt); // [10, NaN, 2, 3, 4 ];
方法与上面同理。
那么将上面的例子转为数字,怎么实现呢?
将parseInt换为Number,将每一个元素转为数字即可
['10', '10', '10', '10', '10'].map(Number);
// [10, 10, 10, 10,10];