JavaScript Puzzlers! 解惑(一):为何 ["1", "2", "3"].map(parseInt) 返回 [1,NaN,NaN]?

JavaScript Puzzlers! 被称为 javascript 界的专业八级考试,感兴趣的 jser 能够去尝尝。
我试了一下, 36 道题只做对了 19 道, 算下来正确率为 53%,还没有合格。

第一题为 ["1", "2", "3"].map(parseInt) 的返回值。

> ["1", "2", "3"].map(parseInt)
[1, NaN, NaN]

在 javascript 中 ["1", "2", "3"].map(parseInt) 为什么返回不是 [1,2,3] 倒是 [1,NaN,NaN]

我们起首回忆一下 parseInt()map() 两个函数的用法:

parseInt() 函数

定义和用法

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

语法

parseInt(string, radix)
参数形貌
string必须。要被剖析的字符串。
radix

可选。示意要剖析的数字的基数。该值介于 2 ~ 36 之间。

假如省略该参数或其值为 `0`,则数字将以 10 为基本来剖析。假如它以 `”0x”` 或 `”0X”` 开首,将以 16 为基数。

假如该参数小于 2 或许大于 36,则 `parseInt()` 将返回 `NaN`。

返回值

返回剖析后的数字。

申明

当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会依据 string 来推断数字的基数。

举例:

  1. 假如 string"0x" 开首,parseInt() 会把 string 的其余部分剖析为十六进制的整数。

  2. 假如 string0 开首,那末 ECMAScript v3 许可 parseInt() 的一个完成把厥后的字符剖析为八进制或十六进制的数字。

  3. 假如 string 以 1 ~ 9 的数字开首,parseInt() 将把它剖析为十进制的整数。

提示和诠释

诠释:只要字符串中的第一个数字会被返回。

诠释:开首和末端的空格是许可的。

提示:假如字符串的第一个字符不能被转换为数字,那末 parseInt() 会返回 NaN

实例

在本例中,我们将运用 parseInt() 来剖析差别的字符串:

parseInt("10");         // 返回 10 (默许十进制)
parseInt("19",10);      // 返回 19 (十进制: 10+9)
parseInt("11",2);       // 返回 3 (二进制: 2+1)
parseInt("17",8);       // 返回 15 (八进制: 8+7)
parseInt("1f",16);      // 返回 31 (十六进制: 16+15)
parseInt("010");        // 不决:返回 10 或 8

map 要领

对数组的每一个元素挪用定义的回调函数并返回包括效果的数组。

array1.map(callbackfn[, thisArg])
参数定义
array1必须。一个数组对象。
callbackfn必须。一个接收**最多**三个参数的函数。关于数组中的每一个元素,`map` 要领都邑挪用 `callbackfn` 函数一次。
thisArg可选。可在 `callbackfn` 函数中为其援用 `this` 关键字的对象。假如省略 `thisArg`,则 `undefined` 将用作 `this` 值。

返回值

个中的每一个元素均为关联的原始数组元素的回调函数返回值的新数组。

非常

假如 callbackfn 参数不是函数对象,则将激发 TypeError 非常。

备注

关于数组中的每一个元素,map 要领都邑挪用 callbackfn 函数一次(采纳升序索引递次)。 不为数组中缺乏的元素挪用该回调函数。

除了数组对象以外,map 要领可由具有 length 属性且具有已按数字编制索引的属性名的任何对象运用。

回调函数语法

回调函数的语法以下所示:

function callbackfn(value, index, array1)

可运用最多三个参数来声明回调函数。

下表列出了回调函数参数。

回调参数定义
value数组元素的值。
index数组元素的数字索引。
array1包括该元素的数组对象。

修正数组对象

数组对象可由回调函数修正。

下表形貌了在 map 要领启动后修正数组对象所取得的效果。

`map` 要领启动后的前提元素是不是传递给回调函数
在数组的原始长度以外增添元素。否。
增添元素以添补数组中缺乏的元素。是,假如该索引还没有传递给回调函数。
元素被变动。是,假如该元素还没有传递给回调函数。
从数组中删除元素。否,除非该元素已传递给回调函数。

示例

下面的示例阐释了 map 要领的用法。

// 定义回调函数
// 盘算圆的面积
function AreaOfCircle(radius) { 
    var area = Math.PI * (radius * radius); 
    return area.toFixed(0); 
} 

// 定义一个数组,庇护三个元素
var radii = [10, 20, 30]; 

// 盘算 radii 的面积. 
var areas = radii.map(AreaOfCircle); 

document.write(areas); 

// 输出: 
// 314,1257,2827

下面的示例阐释 thisArg 参数的用法,该参数指定对其援用 this 关键字的对象。

// 定义一个对象 object,庇护 divisor 属性和 remainder 要领
// remainder 函数求每一个传入的值的个位数。(即除以 10 取余数)
var obj = { 
    divisor: 10, 
    remainder: function (value) { 
        return value % this.divisor; 
    } 
} 

// 定义一个包括 4 个元素的数组
var numbers = [6, 12, 25, 30]; 

// 对 numbers 数组的每一个元素挪用 obj 对象的 remainder 函数。
// map 函数的第 2 个参数传入 ogj。 
var result = numbers.map(obj.remainder, obj); 
document.write(result); 

// 输出: 
// 6,2,5,0

鄙人面的示例中,内置 JavaScript 要领用作回调函数。

// 对数组中的每一个元素挪用 Math.sqrt(value) (求平方根)
var numbers = [9, 16]; 
var result = numbers.map(Math.sqrt); 

document.write(result); 
// 输出: 3,4

[9, 16].map(Math.sqrt) 回调函数,输出的效果是 [3, 4]
然则为什么 ["1", "2", "3"].map(parseInt) 却返回 [1,NaN,NaN]

网站给出的提示是:

what you actually get is [1, NaN, NaN] because parseInt takes two parameters (val, radix) and map passes 3 (element, index, array)

简朴翻译一下就是

parseInt 须要 2 个参数 (val, radix), 而 map 传递了 3 个参数 (element, index, array)」。

经由过程上面的诠释,我们能够看出,假如想让 parseInt(string, radix) 返回 NaN,有两种状况:

  1. 第一个参数不能转换成数字。

  2. 第二个参数不在 2 到 36 之间。

我们传入的参数都能转换成数字,所以只能是第二种能够。

究竟是不是是呢?我们从新定义 parseInt(string, radix) 函数:

var parseInt = function(string, radix) {
    return string + "-" + radix;
};

["1", "2", "3"].map(parseInt);

输出效果为:

["1-0", "2-1", "3-2"]

瞥见,map 函数将数组的值 value 传递给了 parseInt 的第一个参数,将数组的索引传递给了第二个参数。
第三个参数呢?我们再加一个参数

var parseInt = function(string, radix, obj) {
    return string + "-" + radix + "-" + obj;
};

["1", "2", "3"].map(parseInt);

输出效果:

["1-0-1,2,3", "2-1-1,2,3", "3-2-1,2,3"]

我们再继承增添参数:

var parseInt = function(string, radix, obj, other) {
    return string + "-" + radix + "-" + obj + "-" + other;
};

["1", "2", "3"].map(parseInt);

输出效果:

["1-0-1,2,3-undefined", "2-1-1,2,3-undefined", "3-2-1,2,3-undefined"]

第四个参数为 undefined,瞥见 map 确实为 parseInt 传递了三个参数。就像作者写道的:

(element, index, array)
  1. 数组的值

  2. 数组的索引

  3. 数组

UPDATE 原文订正:(感谢 米粽粽 提示)

["1", "2", "3"].map(parseInt)

应当对应的是:

[parseInt("1", 0), parseInt("2", 1), parseInt("3", 2)]

parseInt("3", 2) 的第二个参数是界于 2-36 之间的,之所以返回 NaN 是因为 字符串 "3" 内里没有正当的二进制数,所以 NaN

我们还能够继承实验:

> ["1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"].map(parseInt)
[1, NaN, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

只要当第二个参数是 1 的时刻返回 NaN,别的状况都返回 1

> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"].map(parseInt)
[1, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, 9, 11, 13, 15, 17, 19, 21]

简朴枚举一下:

parseInt("1", 0);    // 十进制 1
parseInt("2", 1);    // 第二个参数不在 2-36 直接
parseInt("3", 2);    // 二进制 NaN
parseInt("4", 3);    // 三进制
parseInt("5", 4);
parseInt("6", 5);
parseInt("7", 6);
parseInt("8", 7);
parseInt("9", 8);
parseInt("10", 9);   // 九进制 (1*9+0 = 9)
parseInt("11", 10);  // 十进制 (1*10+1 = 11)
parseInt("12", 11);
parseInt("13", 12);
parseInt("14", 13);
parseInt("15", 14);
parseInt("16", 15);

(全文完)

文章来自我的个人博客:JavaScript Puzzlers 解密(一):为什么 [“1”, “2”, “3”].map(parseInt) 返回 [1, NaN, NaN]?

    原文作者:justjavac
    原文地址: https://segmentfault.com/a/1190000000411840
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞