为什么使用Array.map(parseInt)在一个字符串数组上会产生不同的结果

4

我正在观看一场关于《摧毁所有软件》主题为JavaScript的诞生和死亡的讲座。

在演讲中,Gary Bernhardt指出了JavaScript的一些奇怪特性。例如,给定一个整数字符串数组,

javascript
var a = ['10','10','10','10']
console.log(a.map(parseInt)); // [10, NaN, 2, 3, 4]

Array.map()接受一个函数,并返回一个新数组,其中包含将此函数应用于每个运算符的结果。

一开始我发现这种行为非常奇怪,parseInt不是将数字解析为整数吗?

为什么会是NaN?而不是10!!


1
我并不是说这是一个糟糕的问题或答案,但既然这是从你的博客抄袭来的,我认为你应该考虑删除这个博客垃圾信息。 - Cᴏʀʏ
这是关于编程的内容,翻译成中文如下:"这非常容易理解,我删除了链接,我对链接到我的博客有些矛盾。" - Amr Draz
1个回答

8

JavaScript常常被拿来开玩笑,因为它似乎会导致意外的结果

var a = []+{} // [Object object]
var b = {}+[] // 0

然而,它的疯狂行为是有一定规律的,我怀疑 parseInt 的行为一定有其原因。

查明问题的根本原因

我起初考虑调试 parseInt,但由于无法调试本地函数,我想到了将其包装在另一个基本执行相同操作的函数周围。

var a = ['10','10','10','10']
var intParse = function (x) {
    return parseInt(x);
};

console.log(a.map(parseInt)); // [10, NaN, 2, 3, 4]
console.log(a.map(intParse)); // [10,10,10,10]

好的,看起来一切都运作良好

但为了简洁起见,我决定尝试更多的观察。

var a;

(a = Array(13).join('10,').split(',')).pop()  // try array of 13 '10's
a.map(parseInt); // [10, NaN, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

(a = Array(10).join('100,').split(',')).pop() // try array of 10 '100's
a.map(parseInt); // [100, NaN, 4, 9, 16, 25, 36, 49, 64, 81]

(a = Array(10).join('7,').split(',')).pop()   // try array of 10 '6's
a.map(parseInt); // [7, NaN, NaN, NaN, NaN, NaN, NaN, 6, 6, 6]

也许这并不奇怪

尽管结果看起来有些奇怪,但它们是一致的(在某种程度上),肯定存在某种模式。

然后我想到了一个点。 Array.map(callback)回调函数需要三个参数:(key, index, array),那么如果parseInt不只接受一个参数,而是接受两个呢?

这肯定会对其结果产生影响。

结果表明parseInt()函数解析一个字符串参数,并返回指定基数或底数的整数。

语法 parseInt(string, radix);

radix是数字的进制数。

parseInt("10", 0) // 10, zero meant decimal
parseInt("10", 1) // NaN, since only 0 is allowed in base 1
parseInt("10", 2) // 2, '10' in binary
parseInt("10", 3) // 3, '10' in ternary
//...

由于 map 回调函数的第二个参数是索引,所以 基数 会根据索引而改变。
这就解释了为什么我的 intParse 函数有效。 我明确指定它只使用带有 x 的 'parseInt'。
我原以为这就是 map 内部的运作方式。
var intParse = function (x) { return parseInt(x);}

事实上,正在发生的就是这样。
var intParse = function (x, r, array) { return parseInt(x, r);}

当我包装函数时,我应该不要假设传递的参数像这样。
var a = ['10','10','10','10']
var intParse = function () {
    return parseInt.apply(this, arguments);
}
console.log(a.map(parseInt)); // [10, NaN, 2, 3, 4]
console.log(a.map(intParse)); // [10, NaN, 2, 3, 4]

学到的经验

这是一次不错的探索,我觉得我对 parseInt 的了解比预期要多。

更重要的是,当程序表现出意外的行为时,很可能有其原因。

最后,如果想要正确地包装一个函数,请使用 .apply(this, arguments)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接