陷阱揭秘:map与parseInt的参数混淆

边缘计算
• 阅读 107

引言

在JavaScript中,[].map() 是数组的一个内置方法,它会创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。让我们分别解析 [].map(parseInt), [].map(parseFloat), 和 [].map(Number) 这三个表达式的含义和预期行为。

[].map(parseInt)

parseInt 是一个全局函数,用于将字符串转换成整数。它接受两个参数:要解析的字符串和一个可选的基数(表示字符串中数字的进制)。在 [].map(parseInt) 中,parseInt 作为 map 的回调函数被传递。

然而,这里存在一个常见的陷阱:map 会在回调函数内部向其传递三个参数:当前元素、元素的索引以及原数组本身。当 parseInt 作为回调函数时,它会接收到这些额外的参数。由于 parseInt 只期望接收一个字符串参数和一个可选的基数参数,它会错误地将 map 传递的索引当作基数来解析字符串。

例如,对于空数组 [],虽然没有实际元素执行 parseInt,但如果有一个非空数组如 ['1', '2', '3'],那么 map 会按如下方式调用 parseInt

parseInt('1', 0); // 第一个元素,索引为0,基数错误地取为0
parseInt('2', 1); // 第二个元素,索引为1,基数错误地取为1
parseInt('3', 2); // 第三个元素,索引为2,基数错误地取为2

由于基数通常应该是2到36之间的整数,这些非标准基数会导致 parseInt 返回 NaN 或意外的结果。因此,['1', '2', '3'].map(parseInt) 通常不会得到预期的 [1, 2, 3],而是 [1, NaN, NaN](或者类似依赖于不同字符串和基数组合的意外结果)。

正确的做法是提供一个自定义的回调函数,确保只传递给 parseInt 字符串参数,并且基数是明确设定的(通常为10,即十进制):

['1', '2', '3'].map(str => parseInt(str, 10));

[].map(parseFloat)

parseFloat 是另一个全局函数,用于将字符串转换成浮点数。与 parseInt 类似,它也只有一个必需参数:要解析的字符串。不过,parseFloat 不关心基数,因为它只处理十进制和指数形式的浮点数。

尽管 parseFloat 不涉及基数问题,但使用 [].map(parseFloat) 仍然可能导致意外结果,因为 map 会传递额外的索引和原数组参数。幸运的是,parseFloat 在忽略多余参数方面表现得更宽容,它只关心第一个参数——要解析的字符串。因此,即使传递了多余的参数,parseFloat 通常仍能正确解析字符串为浮点数。

['1.1', '2.2', '3.3'].map(parseFloat); // [1.1, 2.2, 3.3]

在这个例子中,尽管 map 传递了索引和原数组,但由于 parseFloat 只使用第一个参数,所以它可以正常工作,返回 [1.1, 2.2, 3.3]

[].map(Number)

Number 是一个构造函数,但也可以作为一个函数来使用,它将任何值转换为等效的数字类型。当作为函数调用时,它只接受一个参数,并尝试将其转换为数字。与 parseIntparseFloat 不同,Number 不需要额外的基数参数,且对多种类型的输入值(如字符串、布尔值、null、undefined等)都有明确的转换规则。

使用 [].map(Number) 时,由于 Number 函数只期望一个参数,它可以很好地与 map 的回调函数接口配合,无需担心多余参数的问题。它会将数组中的每个元素尝试转换为数字:

['1', '2', '3'].map(Number); // [1, 2, 3]
['1.1', '2.2', '3.3'].map(Number); // [1.1, 2.2, 3.3]

在这两个例子中,Number 函数成功将字符串数组元素转换为相应的数字,结果分别为 [1, 2, 3][1.1, 2.2, 3.3]

总结

  • [].map(parseInt) 通常导致意外结果,因为 parseInt 误将 map 传递的索引当作基数。需要提供一个自定义回调函数以正确设置基数。
  • [].map(parseFloat) 虽然不涉及基数问题,但由于 map 传递了多余的参数,其行为可能不易预料。幸运的是,parseFloat 通常能正确处理这种情况。
  • [].map(Number) 是最简洁且无陷阱的选择,因为它仅期望一个参数,与 map 回调函数接口完美匹配,且能有效地将各种可转换为数字的值转换为数字。

喜欢的话帮忙点个赞 + 关注吧,将持续更新 JavaScript 相关的文章,还可以关注我的公众号 梁三石FE ,感谢您的关注~

点赞
收藏
评论区
推荐文章
Symbol卢 Symbol卢
4年前
js数组的遍历
js中数组的遍历1\.Map()方法Map映射的意思,可以看做是一个映射函数,所谓的映射。一个萝卜一个坑,一一对应的关系;语法:constarrArray();arr.map((item,index,arr)//函数体return;);//参数1:数组中的每一项(必选)//参数2:索引(可选)//参数3:当前遍历的数组本身(可选)//注
Karen110 Karen110
4年前
盘点JavaScript中数组遍历的全部方式(上篇)
前言JavaScript想必大家都不陌生了,其中的字符串和数组大家经常都会用到,今天就让我们来说说这里面的数组对象的遍历吧,因为遍历经常使用的缘故,所以小编带着大家来解锁遍历的所有方法,以便大家能够更深入的了解数组遍历,并在实际项目中灵活运用。一、Entries这个是ES6中提供的用于遍历数组的方法,它会返回一个遍历器对象,Entries是对键值对的遍历。
Easter79 Easter79
3年前
swift闭包表达式和尾随闭包
我们从一个Swift函数说起。并以此为例子。Swift的标准库提供了一个叫做sorted(by:)的方法,会根据你提供的排序闭包将已知类型的数组的值进行排序。一旦它排序完成,sorted(by:)方法会返回与原数组类型大小完全相同的一个新数组,该数组的元素是已排序好的。原始数组不会被sorted(by:)方法修改。我们以soted方法为例子
LinMeng LinMeng
4年前
js 的 forEach,map,filter,some,every,find(es6),reduce详解
forEach()定义和用法forEach()方法用于调用数组的每个元素,并将元素传递给回调函数注意:forEach()对于空数组是不会执行回调函数的。语法array.forEach(function(currentValue,index,arr),thisValue)参数function(currentValue,index,a
住儿 住儿
2年前
JS的一些优雅写法
JS的一些优雅写法reduce1、可以使用reduce方法来实现对象数组中根据某一key值求和例如,假设有以下对象数组:constarr其中,reduce方法的第一个参数是一个回调函数,它接收两个参数:累加器(acc)和当前元素(cur)。回调函数的返回值
Wesley13 Wesley13
3年前
jdk1.4和jdk1.5的invoke方法的区别
jdk1.4和jdk1.5的invoke方法的区别jdk1.5:publicObjectinvoke(Objectobj,Object...args)jdk1.4publicObjectinvoke(Objectobj,Object\\args)按1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别
菜园前端 菜园前端
2年前
什么是高阶函数?
原文链接:什么是高阶函数?有两种情况都可以被定义为高阶函数,第一种是把函数作为参数传递给另外一个函数,第二种是把函数作为另一个函数的返回结果。就像我们平时调用函数,一般都是传递值类型或者对象和数组等参数,或者是函数返回结果是值类型或者是对象和数组,高阶函数
Stella981 Stella981
3年前
JavaScript基础知识
题目:1.找出数字数组中最大的元素(使用Math.max函数)2.转化一个数字数组为function数组(每个function都弹出相应的数字)3.给object数组进行排序(排序条件是每个元素对象的属性个数)4.利用JavaScript打印出Fibonacci数(不使用全局变量)5.实现如下语法的功能:vara(5).plus(
Stella981 Stella981
3年前
JavaScript 转换数字为整数的方法
本文将会列举并说明JavaScript把一个number(或者numerical的对象)转换成一个整数相关方法。使用parseIntparseInt的语法如下:parseInt(string,radix)参数string的表示要解析的字符串,也可以是一个对象,会自动调用对象的toString函数得到要解析的字符
Stella981 Stella981
3年前
Google布隆过滤器与Redis布隆过滤器详解
一、什么是布隆过滤器?布隆过滤器可以用来判断一个元素是否在一个集合中。它的优势是只需要占用很小的内存空间以及有着高效的查询效率。对于布隆过滤器而言,它的本质是一个位数组:位数组就是数组的每个元素都只占用1bit,并且每个元素只能是0或者1布隆过滤器除了一个位数组,还有K个哈希函数。当一个元素加入布隆过滤器中的时候,会进行如下操作:
Wesley13 Wesley13
3年前
C#图解教程 第十二章 数组
数组数组数组实际上是由一个变量名称表示的一组同类型的数据元素。每个元素通过变量名称和一个或多个方括号中的索引来访问:数组名索引↓↓MyArray4定义让我们从C中与数组有关的重要定义开始元素数组的独立数据项称为元素。数组的所有元素必须