为何["1","2","3"].map(parseInt) 返回[1,NaN,NaN]?

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

咱们使用进制的相关知识来解释说明,若是你看完仍是没有很清楚,能够本身去了解一些进制的相关知识。java

咱们首先回顾一下 parseInt()map() 两个函数的用法:数组

一、parseInt() 函数:

parseInt() 函数可解析一个字符串,并返回一个整数,可有两个参数。浏览器

//语法:
parseInt(string, radix)
复制代码
参数 描述
string 必需。要被解析的字符串。
radix

可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。bash

若是省略该参数或其值为 0,则数字将以 10 为基础来解析。函数

一、当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。ui

当忽略参数 radix , JavaScript 默认数字的基数以下:this

(1)若是 string 以 "0x"或 “0X” 开头,parseInt() 会把 string 的其他部分解析为十六进制的整数。spa

(2)若是 string 以 0 开头,那么 ECMAScript v3 容许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。code

(3)若是 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。

二、若是该参数小于 2 或者大于 36,则返回 NaN

提示和注释

(1)只有字符串中的第一个数字会被返回。

(2)开头和结尾的空格是容许的。

(3)若是字符串的第一个字符不能被转换为数字,则返回 NaN。

(4)在字符串以"0"为开始时旧的浏览器默认使用八进制基数。ECMAScript 5,默认的是十进制的基数。

//当忽略参数 radix 
parseInt("10")//1*10^1+0*10^0=10  
parseInt("10.33")//1*10^1+0*10^0=10 
parseInt("34 45 66") //3*10^1+4*10^0=34 
parseInt(" 60 ") //6*10^1+0*10^0=60 
parseInt("40 years")  //4*10^1+0*10^0=40 
parseInt("He was 40")  //NaN 
parseInt("1f",16);		//1*16^1+f*16^0=16+15=31
parseInt("0x10")//1*16^1+0*16^0=16  string 以 "0x" 开头,会把 string 的其他部分解析为十六进制的整数 
parseInt("010")//0*10^2+1*10^1+0*10^0=10 或  0*8^2+1*8^1+0*8^0=8  string 以 0 开头,旧浏览器默认使用八进制基数。ECMAScript 5,默认的是十进制的基数。

//当有参数 radix,表示以radix为基数解析
parseInt("10",10) //1*10^1+0*10^0=10 
parseInt("10",8)//1*8^1+0*8^0=8
parseInt("10",16) //1*16^1+0*16^0=16复制代码

咱们还须要了解进制数的相关知识:

二进制的定义:用0和1两个数码来表示的数。

三进制的定义:用0和1,2三个数码来表示的数......

十进制的定义:用0和1,2,3...9十个数码来表示的数。

十进制分别转为2、3、四进制的值
十进制 二进制 三进制 四进制
0 0 0 0
1 1 1 1
2 10 2 2
3 11 10 3
4 100 11 10
5 101 12 11
6 110 20 12
7 111 21 13
8 1000 22 20
9 1001 100 21
10 1010 101 22
//以2为基数,
parseInt('1', 2)//1
parseInt('2', 2)//NaN
parseInt('3', 2)//NaN
parseInt('10',2)//2
//以3为基数,
parseInt('1', 3)//1
parseInt('2', 3)//2
parseInt('3', 3)//NaN
parseInt('10',3)//3
//以4为基数,
parseInt('1', 4)//1
parseInt('2', 4)//2
parseInt('3', 4)//3
parseInt('4', 4)//NaN
parseInt('10',4)//4
......

//总结:
咱们能够这样理解,二进制里没有2,3,...9,三进制里没有3,4...9,四进制里没有4,5...9
即当string没法转成radix基数时会返回NaN
复制代码

由上可知,相关文档只说明了两种状况会返回NaN,实际上还存在上面代码的状况:当string没法转成radix进制数时会返回NaN

可是为何 ["1","2","3"].map(parseInt) 却返回 [1,NaN,NaN]parseInt 须要 2 个参数 (val, radix), 而 map 传递了 3 个参数 (element, index, array)。

回到原题,作出解释:

['1','2','3'].map(parseInt)
//  parseInt('1', 0) -> 1   //radix=0,以10为基数解析 1*10^1+0*10^0=10
//  parseInt('2', 1) -> NaN //radix=1<2,返回NaN
//  parseInt('3', 2) -> NaN //3没法转成二进制

//即遍历后结果为 [1,NaN,NaN]
复制代码

以上为题的正解说明。

咱们接着来讲map( )的用法:

二、map()方法:

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

//语法:
array.map(function(currentValue,index,arr), thisValue)
复制代码
参数 描述
function(currentValue, index,arr)
必须。函数,数组中的每一个元素都会执行这个函数
函数参数:
参数 描述
currentValue
必须。当前元素的值
index
可选。当前元素的索引值
arr
可选。当前元素属于的数组对象
thisValue
可选。对象做为该执行回调时使用,传递给函数,用做 "this" 的值。
若是省略了 thisValue ,"this" 的值为 "undefined"

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

对于数组中的每一个元素,map 方法都会调用 callbackfn 函数一次(采用升序索引顺序)。 不为数组中缺乏的元素调用该回调函数。

下面的示例阐释了 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); // 314,1257,2827复制代码

下面的示例阐释thisValue参数的用法,该参数指定对其引用 this 关键字的对象,至关于给map的回调函数指定了this对象:

// 定义一个对象 object,保护 divisor 属性和 remainder 方法
// remainder 函数求每一个传入的值的个位数。(即除以 10 取余数)
var obj = { 
    divisor: 10, 
    remainder: function (value) { 
        return value % this.divisor; 
    } 
} 
var numbers = [6, 12, 25, 30]; 

divisor = 6;
function remainder(value) {
return value % this.divisor;
}

numbers.map(obj.remainder, obj); //[6,2,5,0] obj.remainder this=obj
numbers.map(remainder, obj);//[ 6,2,5,0] window.remainder this=obj
numbers.map(remainder);//[0,0,1,0] window.remainder this=window 
numbers.map(obj.remainder);//[0,0,1,0] obj.remainder this=window 
//有两个remainder函数,第一步肯定调用的是哪个,第二步肯定执行的时候this是谁复制代码
从新定义 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"]
//"-" + obj 致使obj调用toString()方法自动转换为了string,至关于链接符
//第1次遍历:1 + "-" + 0 + "-" + [1,2,3]="1-0-1,2,3"

//toString()还有如下几种特殊状况
[{a:1},{b:2}].toString()//"[object Object],[object Object]"
[1,2].toString()//"1,2"
[[1,2],[3,4]].toString()//"1,2,3,4"复制代码
相关文章
相关标签/搜索