1. 首页
  2. 前端进阶
  3. JavaScript

JavaScript 中为啥 [‘1’, ‘7’, ’11’].map(parseInt) 返回 [1, NaN, 3]

Javascript 一直是神奇的语言。 不相信我? 尝试使用mapparseInt将字符串数组转换为整数。打开 Chrome 的控制台(F12),粘贴以下内容,然后按回车,查看输出结果:

[’1′, ‘7’, ’11’].map(parseInt);

我们得到的不是一个整数数组[1,7,11],而是[1,NAN, 3],要了解究竟发生了什么,我们首先要讨论一些Javascript概念。

真值(truthy) & 虚值(falsy)

以下是 JS 中一个简单的if-else语句:

JS中文网 – 前端进阶资源教程 https://www.javascriptc.com/
一个致力于帮助开发者用代码改变世界为使命的平台,每天都可以在这里找到技术世界的头条内容


if (true) { // this always runs } else { // this never runs }

在上例中,if 条件为 true,因此总是执行if块,忽略else块。这是一个简单的例子,因为true是一个布尔值。如果我们把非布尔值作为条件呢 ?


if ("hello world") { console.log("Condition is truthy"); } else { console.log("Condition is falsy"); }

打开控制台并运行上述代码,会打印 Condition is truthy,说明条件 "hello world"真(true)值。

在 JavaScript 中,Truthy (真值)指的是在 布尔值 上下文中转换后的值为真的值。所有值都是真值,除非它们被定义为 falsy (即除了 false0""nullundefinedNaN 外)。

falsy(虚值)是在 Boolean 上下文中已认定可转换为‘假‘的值。

JS中的对象不是真值就是虚值。

令人困惑的是,这意味着字符串“false”,字符串“0”,空对象{}和空数组[]都是真的。 使用使用 Boolean 方法来验证,如 Boolean("0")

出于我们的目的,接下来只要记住0是假的就行了。

基数

在数学上,基数(cardinal number)是集合论中刻画任意集合大小的一个概念。两个能够建立元素间一一对应的集合称为互相对等集合。例如3个人的集合和3匹马的集合可以建立一一对应,是两个对等的集合。


0 1 2 3 4 5 6 7 8 9 10

当我们从0数到9时,每个数字(0-9)都有不同的符号,但是当我们数到10时,我们需要两个不同的符号(10)来表示这个数字。这是因为我们的十进制计数系统的基数是10

基数是最小的数字,只能由多个符号表示。 不同的计数系统具有不同的基数,因此,相同的数字在不同的计数系统中可以表示不同的数字。


十进制 二进制 十六进制 RADIX=10 RADIX=2 RADIX=16 0 0 0 1 1 1 2 10 2 3 11 3 4 100 4 5 101 5 6 110 6 7 111 7 8 1000 8 9 1001 9 10 1010 A 11 1011 B 12 1100 C 13 1101 D 14 1110 E 15 1111 F 16 10000 10 17 10001 11

看上表,可以看到相同的数字11在不同的计数系统中可以表示不同的数字。如果基数是2,那么它表示数字为 3。如果基数是16,那么它指的是数字17

你可能已经注意到,在我们的示例中,当输入为11时,parseInt返回3,这对应于上表中的二进制列。

函数参数

JS 中函数调用,我们可以传入任意的参数,即使它们不等于声明时的函数参数的数量。缺少的参数被视为undefined 的,并且会忽略额外的参数,但会保存在类似数组的arguments对象中。


function foo(x, y) { console.log(x); console.log(y); } foo(1, 2); // 打印 1, 2 foo(1); // 打印 1, undefined foo(1, 2, 3); // 打印 1, 2

map()

map是 Es6 中新出的一个数组方法,它是一个高阶函数,通过传入一个函数进行逻辑操作,并返回一个数组, 例如,以下代码将数组中的每个元素乘以3


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作为参数传给 map,来打印数组的元素:


[1, 2, 3, 4, 5].map(console.log); 等价于 [1, 2, 3, 4, 5].map((val, index, array) => console.log(val, index, array));

码农进阶题库,每天一道面试题 or Js小知识

所以 map 回调方法中会传入三个参数,分别是 当前遍历的项,当前索引,及遍历的整个数组。

原因

ParseInt有两个参数:stringradix。 如果提供的基数是虚值,则默认情况下,基数设置为10


parseInt('11'); => 11 parseInt('11', 2); => 3 parseInt('11', 16); => 17 parseInt('11', undefined); => 11 (radix is falsy) parseInt('11', 0); => 11 (radix is falsy)

现在一步一步解析开头的事例。


['1', '7', '11'].map(parseInt); => [1, NaN, 3] // 第一次迭代: val = '1', index = 0, array = ['1', '7', '11'] parseInt('1', 0, ['1', '7', '11']); => 1

因为0是虚值,基数设置为默认值10parseInt()只接受两个参数,因此忽略了第三个参数['1'、'7'、'11']。以10为基数的字符串“1”表示数字1


// 第二次迭代: val = '7', index = 1, array = ['1', '7', '11'] parseInt('7', 1, ['1', '7', '11']); => NaN

在基数1系统中,符号“7”不存在。与第一次迭代一样,忽略最后一个参数。因此,parseInt()返回NaN


// Third iteration: val = '11', index = 2, array = ['1', '7', '11'] parseInt('11', 2, ['1', '7', '11']); => 3

在基数2(二进制)系统中,符号“11”表示数字3

至此原因已经明了了。 有兴趣可以试着写下下列的打印结果:


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

前端进阶教程,BAT面试题
https://www.javascriptc.com/interview-tips/

作者:前端小智
链接:https://segmentfault.com/a/1190000019479803

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「IT平头哥联盟」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:JavaScript 中为啥 [‘1’, ‘7’, ’11’].map(parseInt) 返回 [1, NaN, 3]

链接:https://www.javascriptc.com/3517.html

« React 项目结构和组件命名规范
webpack 插件化设计»
Flutter 中文教程资源

相关推荐

QR code