JavaScript 经常成为模仿对象,因为它看似 unexpected results。
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]
好的,看来一切正常fine
但为了简洁起见,我决定尝试更多观察
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) 回调接受 3 个参数,(key, index, array),那么如果 parseInt 不只接受一个参数,而是接受 2 个参数呢。
这肯定会对结果产生影响
Turns outparseInt() 函数解析字符串参数并返回指定基数或基数的整数。
语法
parseInt(string, 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'。
我以为这就是地图内部发生的事情
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)