refactor(blog): restructure blog post layouts and metadata docs: add markdown migration guide and project rules update style(global.css): update typography theme variables chore: move temp_docs to appropriate blog post locations
86 lines
3.6 KiB
Markdown
86 lines
3.6 KiB
Markdown
---
|
||
layout: "@/layouts/BlogPostLayout.astro"
|
||
title: "JavaScript中map遍历数字的陷阱"
|
||
description: "本文详细解析了JavaScript中[\"1\",\"2\",\"3\"].map(parseInt)返回[1, NaN, NaN]的原因,通过分析map和parseInt方法的工作原理,揭示了这个常见的JavaScript陷阱。"
|
||
date: "2023-09-15"
|
||
image: "https://images.unsplash.com/photo-1579468118864-1b9ea3c0db4a?q=80&w=1470&auto=format&fit=crop"
|
||
tags: ["JavaScript", "函数式编程", "陷阱"]
|
||
tagId: ["javascript", "functional-programming", "trap"]
|
||
category: "前端开发"
|
||
categoryId: "frontend"
|
||
readTime: "3 min read"
|
||
---
|
||
|
||
在JavaScript中,有一个经典的问题:
|
||
|
||
```javascript
|
||
["1","2","3"].map(parseInt)
|
||
```
|
||
|
||
|
||
这段代码的返回值是什么?很多人可能会认为是`[1, 2, 3]`,但实际上是`[1, NaN, NaN]`。为什么会这样呢?让我们一起来分析一下。
|
||
|
||
### map方法的工作原理
|
||
|
||
首先,我们需要了解`map`方法的工作原理。`map`方法会为数组中的每个元素调用一次提供的函数,并使用函数的返回值创建一个新数组。
|
||
|
||
`map`方法的回调函数接受三个参数:
|
||
|
||
1. `currentValue`:当前正在处理的元素
|
||
2. `index`:当前元素的索引
|
||
3. `array`:调用`map`方法的数组
|
||
|
||
所以,当我们执行`["1","2","3"].map(parseInt)`时,实际上是在执行:
|
||
|
||
```javascript
|
||
["1","2","3"].map((item, index, array) => parseInt(item, index, array))
|
||
```
|
||
|
||
|
||
### parseInt方法的工作原理
|
||
|
||
接下来,我们需要了解`parseInt`方法的工作原理。`parseInt`方法解析一个字符串参数,并返回一个指定基数的整数。
|
||
|
||
`parseInt`方法接受两个参数:
|
||
|
||
1. `string`:要被解析的值。如果参数不是一个字符串,则将其转换为字符串。字符串开头的空白符将会被忽略。
|
||
2. `radix`:一个介于2和36之间的整数,表示上述字符串的基数。例如,指定10表示使用十进制数值系统。始终指定此参数可以消除阅读该代码时的困惑并且保证转换结果可预测。当未指定基数时,不同的实现会产生不同的结果,通常将值默认为10。
|
||
|
||
### 分析问题
|
||
|
||
现在,让我们分析一下`["1","2","3"].map(parseInt)`的执行过程:
|
||
|
||
1. 对于第一个元素"1",`map`方法调用`parseInt("1", 0, ["1","2","3"])`。由于`radix`为0,`parseInt`会根据字符串的前缀来决定基数。如果字符串不以"0x"或"0"开头,则基数为10。所以,`parseInt("1", 0)`返回1。
|
||
|
||
2. 对于第二个元素"2",`map`方法调用`parseInt("2", 1, ["1","2","3"])`。由于`radix`为1,而有效的`radix`范围是2-36,所以`parseInt("2", 1)`返回`NaN`。
|
||
|
||
3. 对于第三个元素"3",`map`方法调用`parseInt("3", 2, ["1","2","3"])`。由于`radix`为2,表示二进制,而在二进制中只有0和1,所以`parseInt("3", 2)`返回`NaN`。
|
||
|
||
因此,`["1","2","3"].map(parseInt)`的返回值是`[1, NaN, NaN]`。
|
||
|
||
### 如何正确使用
|
||
|
||
如果我们想要将字符串数组转换为数字数组,可以使用以下方法:
|
||
|
||
```javascript
|
||
["1","2","3"].map(Number) // [1, 2, 3]
|
||
```
|
||
|
||
或者使用箭头函数:
|
||
|
||
```javascript
|
||
["1","2","3"].map(item => parseInt(item)) // [1, 2, 3]
|
||
```
|
||
|
||
或者使用`parseInt`的绑定函数:
|
||
|
||
```javascript
|
||
["1","2","3"].map(parseInt.bind(null)) // [1, 2, 3]
|
||
```
|
||
|
||
|
||
### 总结
|
||
|
||
这个问题揭示了JavaScript中函数式编程的一个常见陷阱。当我们使用高阶函数如`map`时,需要注意回调函数的参数和行为。在这个例子中,`parseInt`函数接受的参数与`map`方法提供的参数不完全匹配,导致了意外的结果。
|
||
|
||
理解这个问题有助于我们更好地理解JavaScript中的函数式编程和类型转换。 |