['1', '7', '11'].map(parseInt)

相信很多人会对上面的执行结果感到疑惑,不要着急,相信看完这篇文章后,你会对javascript的运行机制又有更进一步的理解。

首先我们需要澄清以下几个概念:

Boolean 对象

1
2
3
4
5
6
7
if ("hello world") {
// will this run?
console.log("Condition is truthy");
} else {
// or this?
console.log("Condition is falsy");
}

上述代码会输出Condition is truthy

Boolean(布尔)对象用于将非布尔值转换为布尔值( "true" 或者 "false"),

Boolean对象的值为:

  • 0
  • -0
  • null
  • “”
  • false
  • undefined
  • NaN

那么对象的值为 false。否则,其值为 true(包括:“false”, "0", {}[])!

arguments对象

在Javascript函数参数个数是不固定的, 即使他们不等于声明函数参数的数量。缺少的参数被当做undefined的和多余的参数会被忽略

1
2
3
4
5
6
7
8
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

Array map()的用法

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

1
2
3
4
5
function multiplyBy3(x) {
return x * 3;
}
const result = [1, 2, 3, 4, 5].map(multiplyBy3);
console.log(result); // logs [3, 6, 9, 12, 15];

传入console.log用于输出数组中的每个元素:

1
[1, 2, 3, 4, 5].map(console.log);

[1, 2, 3, 4, 5].map(console.log)

神奇的事情发生了,结果并不是我们预想的,输出的是每个元素,元素的下标和整个数组对象。

当一个函数被传入map中,这个函数被传入三个参数: currentValue, currentIndexarray

1
2
3
4
5
6
7
8
9
[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)
);

言归正传

现在是时候回到文章开头提到的问题了。

为什么[‘1’, ‘7’, ‘11’].map(parseInt)返回值是[1, NaN, 3]呢?

parseInt用法

parseInt() 函数可解析一个字符串,并返回一个整数。

语法:

parseInt(string, radix)

参数 描述
string 必需。要被解析的字符串。
radix 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。

如果radix参数省略或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。

我们看几个例子:

1
2
3
4
5
parseInt('11');                => 11
parseInt('11', 2); => 3
parseInt('11', 16); => 17
parseInt('11', undefined); => 11 (radix is false)
parseInt('11', 0); => 11 (radix is false)

基于上述的理解,我们对['1', '7', '11'].map(parseInt)的推演过程:

1
2
3
4
5
6
7
8
['1', '7', '11'].map(parseInt);       => [1, NaN, 3]

// 第一次遍历: val = '1', index = 0, array = ['1', '7', '11']
parseInt('1', 0, ['1', '7', '11']); => 1
// 第二次遍历: val = '7', index = 1, array = ['1', '7', '11']
parseInt('7', 1, ['1', '7', '11']); => NaN
// 第三次遍历: val = '11', index = 2, array = ['1', '7', '11']
parseInt('11', 2, ['1', '7', '11']); => 3

由于parseInt只接收两个参数,自动会忽略第三个参数。

parseInt('1', 0): 由于radix参数传入了0,那么默认以10为基础计算,所以得到 1

parseInt('7', 1): 由于radix参数传入了1,返回 NaN

parseInt('11', 2): 由于radix参数传入了2,返回 3

思考

我们已经知道['1', '7', '11'].map(parseInt)输出的结果[1, Nan, 3], 如果想得到[1, 7, 11]这样的结果,应该如何处理呢?

给你们思考3分钟吧 😝😝😝

1
['1', '7', '11'].map(numStr => parseInt(numStr));

你想到了吗?