21

为什么['1', '7', '11'].map(parse...

 4 years ago
source link: https://answer518.github.io/2020/01/12/parseint-mystery-research/?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
['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对象的值为:

  • false
  • undefined

那么对象的值为 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));

你想到了吗?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK