js 疑难杂症
["1", "2", "3"].map(parseInt)?
=>
[1,NAN, NAN]
原因:parseInt接收的是两个参数,map传递的是3个参数。
map指定传入的函数参数作为callbackfn.规范里指出:“callbackfn调用时需要传入三个参数:元素的值,元素的索引和正在被遍历的对象”。仔细体会一下,原本我们以为对parseInt的三次调用是这样:
parseInt('1')
parseInt('2')
parseInt('3')
然而实际上是这样调用的:
parseInt('1',0,theArray);
parseInt('2',1,theArray);
parseInt('3',2,theArray);
这里theArray 就是原始数组[‘1’,’2’,’3’]。
JS函数一般会自动忽视多余的参数,
parseInt(string, radix);
string: 需要转化的字符,如果不是字符串会被转换,忽视空格符。
radix:数字2-36之前的整型。默认使用10,表示十进制。
需要注意的是,如果radix在2-36之外会返回NaN。
parseInt仅仅需要两个参数,所以我们并不需要担心这个theArray参数对parseInt的影响。
重点来了,第二个参数是如何影响parseInt的
在第一次调用时,parseInt的第二个参数是0,上面已经说了,所以第一调用
parseInt('1',0) 返回1. 第二次调用第二个参数是1,也是说1作为数值的基础。规范里说的很清楚了,如果基础是非0或者小于2,函数都不会查询字符串直接返回NaN。 第三次调用时,2作为基数。这就意味着字符串将被解析成字节数,也就是仅仅包含数值0和1。parseInt的规范第十一步指出,它仅尝试分析第一个字符的左侧,这个字符还不是要求基数的有效数字。这个字符串的第一个字符是“3”,它并不是基础基数2的一个有效数字。所以这个子字符串将被解析为空。第十二步说了:如果子字符串被解析成空了,函数将返回为NaN。
所以这里的结果就应该是[1,NaN,NaN].
这里问题所在就是容易忽视parseInt是需要两个参数的。map中有三个参数。所以这里结合起来,就导致了上面问题。
解决方法:
['1','2','3'].map(function(value){
return parseInt(value)
})
当然,我们也可以写:
['1','2','3'].map(Number)
数据拼接的一个问题?
let a = [1,2];
let b = [{n:"a"},{n:"b"}];
let c1 = a.map(e=>{
return b.map(f=>{
f.m=e
return f;
})
})
c1
打开chorme 开发者工具在console下输入上面代码查看c1的输出结果,发现并不如我们期望的那样。
再看下下面的输出结果,发现才是我们想要的。
let c2 = a.map(e=>{
return [{n:"a"},{n:"b"}].map(f=>{
f.m=e
return f;
})
})
c2
但我们在实际工作中不可能这样写,所以正确做法是:
let c3 = a.map(e=>{
return b.map(f=>{
return {
n:f.n,
m:e
};
})
})
or
let c1 = a.map((e) => {
let obj = b.map((f) => {
f.m = e;
return f;
});
return JSON.parse(JSON.stringify(obj));
});
(本文不定期更新)