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

javascript中的parseInt与map函数都是常用的函数,可是 ["1", "2", "3"].map(parseInt) 为何返回不是[1,2,3]却是[1,NaN,NaN]?

这涉及到是否深入理解两个函数的格式与参数含义。

首先根据我对两个函数用法的了解,猜测是由于parseInt(stringradix) 的参数radix必须介于2~36之间,而且字符串string中的数字不能大于radix才能正确返回数字结果值。

我们通过以下javascript代码测试一下:

[javascript] view plaincopy

  1. var a=["1", "2", "3", "4","5",6,7,8,9,10,11,12,13,14,15];
  2. a.map(parseInt);

返回结果为:[1,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,9,11,13,15,17,19]

正好印证了以上的猜测是正确的,因为:

parseInt(‘1‘,0) = 1,
parseInt(‘2‘,1) = NaN,
parseInt(‘3‘,2) = NaN,
……

正是由于map的回调函数的参数index索引值作了parseInt的基数radix,导致出现超范围的radix赋值和不合法的进制解析,才会返回NaN。

也许你还会怀疑索引值和基数radix对应关系的准确性,这时你可以重新定义parseInt函数,再来测试一下:

[javascript] view plaincopy

  1. function parseInt(str, radix) {
  2. return str+‘-‘+radix;
  3. };
  4. var a=["1", "2", "3", "4","5",6,7,8,9,10,11,12,13,14,15];
  5. a.map(parseInt);

输出结果为:["1-0","2-1","3-2","4-3","5-4","6-5","7-6","8-7","9-8","10-9","11-10","12-11","13-12","14-13","15-14"]。

通过此例,再次证明,索引index的起始值从0开始,与radix的对应如前陈述一致,所以才会出现返回NaN的类型值。

这个实例提醒我们在使用两个函数parseInt和map时候要格外小心。同时对于IE6-7不支持map函数的情况也要谨慎或者通过prototype扩展处理。

最后再仔细回顾温习一下:

parseInt() 函数

定义和用法

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

语法

parseInt(string, radix)
参数 描述
string 必需。要被解析的字符串。
radix
可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。

如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。

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

返回值

返回解析后的数字。

说明

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

举例,如果 string 以 "0x" 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。如果string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。如果string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。

提示和注释

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

注释:开头和结尾的空格是允许的。

提示:如果字符串的第一个字符不能被转换为数字,那么 parseFloat() 会返回 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 方法 (Array) (JavaScript)

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

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 方法的用法。

// Define the callback function. 
function AreaOfCircle(radius) { 
    var area = Math.PI * (radius * radius); 
    return area.toFixed(0); 
} 
 
// Create an array. 
var radii = [10, 20, 30]; 
 
// Get the areas from the radii. 
var areas = radii.map(AreaOfCircle); 
 
document.write(areas); 
 
// Output: 
// 314,1257,2827

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

// Define an object that contains a divisor property and 
// a remainder function. 
var obj = { 
    divisor: 10, 
    remainder: function (value) { 
        return value % this.divisor; 
    } 
} 
 
// Create an array. 
var numbers = [6, 12, 25, 30]; 
 
// Get the remainders. 
// The obj argument specifies the this value in the callback function. 
var result = numbers.map(obj.remainder, obj); 
document.write(result); 
 
// Output: 
// 6,2,5,0

在下面的示例中,内置 JavaScript 方法用作回调函数。

// Apply Math.sqrt(value) to each element in an array. 
var numbers = [9, 16]; 
var result = numbers.map(Math.sqrt); 
 
document.write(result); 
// Output: 3,4

map 方法可应用于字符串。 下面的示例阐释了这一点。

// Define the callback function. 
function threeChars(value, index, str) { 
    // Create a string that contains the previous, current, 
    // and next character. 
    return str.substring(index - 1, index + 2); 
} 
 
// Create a string. 
var word = "Thursday"; 
 
// Apply the map method to the string. 
// Each array element in the result contains a string that 
// has the previous, current, and next character. 
// The commented out statement shows an alternative syntax. 
var result = [].map.call(word, threeChars); 
// var result = Array.prototype.map.call(word, threeChars); 
 
document.write(result); 
 
// Output: 
// Th,Thu,hur,urs,rsd,sda,day,ay 

要求

在以下文档模式中受支持:Internet Explorer 9 标准模式、Internet Explorer 10 标准模式和 Internet Explorer 11 标准模式。Windows 应用商店 应用程序中也支持此项。请参阅版本信息

在以下文档模式中不受支持:Quirks、Internet Explorer 6 标准模式、Internet Explorer 7 标准模式、Internet Explorer 8 标准模式。

最后再援引一篇文章:JavaScript数组遍历map()的原型扩展http://www.nowamagic.net/librarys/veda/detail/783

在 JavaScript 1.6 里,javascript 数组增加了几个非常有用的方法:indexOf、lastIndexOf、every、 filter、 forEach、 map、 some,其中前两个可以归为元素定位方法,而后面的几个则可以归为迭代(iterative)方法。

遗憾的是:这些新方法并非所有浏览器都支持,在这种情况下,我们就需要自己动手了,在这些介绍的文章中,我们同时提供了在不支持这些新特性的浏览器中的实现方法。

原生方法如下:

1 var mappedArray = array.map(callback[, thisObject]);
  • callback: 要对每个数组元素执行的回调函数。
  • thisObject : 在执行回调函数时定义的this对象。

对数组中的每个元素都执行一次指定的函数(callback),并且以每次返回的结果为元素创建一个新数组。它只对数组中的非空元素执行指定的函数,没有赋值或者已经删除的元素将被忽略。

回调函数可以有三个参数:当前元素,当前元素的索引和当前的数组对象。如参数 thisObject 被传递进来,它将被当做回调函数(callback)内部的 this 对象,如果没有传递或者为null,那么将会使用全局对象。

map 不会改变原有数组,记住:只有在回调函数执行前传入的数组元素才有效,在回调函数开始执行后才添加的元素将被忽略,而在回调函数开始执行到最后一个元素这一期间,数组元素被删除或者被更改的,将以回调函数访问到该元素的时间为准,被删除的元素将被忽略。

如果浏览器不支持map方法,也可以按照下面的方式用prototype去扩展:

01 <script type="text/javascript">
02 //扩展原型对象
03 Array.prototype.map = function(fn){
04     vara = [];
05     for(vari = 0; i < this.length; i++){
06         varvalue = fn(this[i], i);
07         if(value ==null){
08             continue;//如果函数fn返回null,则从数组中删除该项
09         }
10         a.push(value);
11     }
12     returna;
13 };
14  
15 //例子,arr为原始数组
16 var arr = [
17     {name: ‘gonn‘, age: 20, sex: ‘1‘, No:‘274200‘},
18     {name: ‘nowamagic‘, age: 30, sex: ‘0‘, No: ‘274011‘},
19     {name: ‘frie‘, age: 40, sex: ‘1‘, No:‘274212‘}
20     ];
21   
22 //使用map更改数组每项的值,可对数组每一项元素内部进行增删改,也可以通过return null来删除数组的某项
23 var arr2 = arr.map(function(item, i){
24     item.sex = item.sex ==‘0‘ ‘女‘‘男‘;
25     if(item.name ==‘tom‘){
26         returnnull//删除name为tom的项
27     }
28     return{
29         index: i,
30         name: item.name,
31         age: item.age + 30 + i,
32         sex: item.sex
33     };
34 });
35   
36 console.log(arr2);
37 </script>

在Firefox firebug控制台输出:

1 [
2 Object { index=0, name="gonn", age=50, 更多...},
3 Object { index=1, name="nowamagic", age=61, 更多...},
4 Object { index=2, name="frie", age=72, 更多...}
5 ]

或者以下方式扩展也可以:

01 if (!Array.prototype.map)
02 {
03     Array.prototype.map =function(fun /*, thisp*/)
04     {
05         varlen = this.length;
06         if(typeof fun != "function")
07             thrownew TypeError();
08   
09         varres = new Array(len);
10         varthisp = arguments[1];
11         for(var i = 0; i < len; i++)
12         {
13             if(i in this)
14                 res[i] = fun.call(thisp,this[i], i, this);
15         }
16   
17         returnres;
18     };
19 }

注:map返回的是新数组,它不修改调用的数组。

为了兼容不支持map的浏览器,developer.mozilla.org上给出了map兼容性解决方法。

[javascript] view plaincopy

  1. // Production steps of ECMA-262, Edition 5, 15.4.4.19
  2. // Reference: http://es5.github.com/#x15.4.4.19
  3. if (!Array.prototype.map) {
  4. Array.prototype.map = function(callback, thisArg) {
  5. var T, A, k;
  6. if (this == null) {
  7. throw new TypeError(" this is null or not defined");
  8. }
  9. // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
  10. var O = Object(this);
  11. // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
  12. // 3. Let len be ToUint32(lenValue).
  13. var len = O.length >>> 0;
  14. // 4. If IsCallable(callback) is false, throw a TypeError exception.
  15. // See: http://es5.github.com/#x9.11
  16. if (typeof callback !== "function") {
  17. throw new TypeError(callback + " is not a function");
  18. }
  19. // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
  20. if (thisArg) {
  21. T = thisArg;
  22. }
  23. // 6. Let A be a new array created as if by the expression new Array(len) where Array is
  24. // the standard built-in constructor with that name and len is the value of len.
  25. A = new Array(len);
  26. // 7. Let k be 0
  27. k = 0;
  28. // 8. Repeat, while k < len
  29. while(k < len) {
  30. var kValue, mappedValue;
  31. // a. Let Pk be ToString(k).
  32. //   This is implicit for LHS operands of the in operator
  33. // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
  34. //   This step can be combined with c
  35. // c. If kPresent is true, then
  36. if (k in O) {
  37. // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
  38. kValue = O[ k ];
  39. // ii. Let mappedValue be the result of calling the Call internal method of callback
  40. // with T as the this value and argument list containing kValue, k, and O.
  41. mappedValue = callback.call(T, kValue, k, O);
  42. // iii. Call the DefineOwnProperty internal method of A with arguments
  43. // Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
  44. // and false.
  45. // In browsers that support Object.defineProperty, use the following:
  46. // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
  47. // For best browser support, use the following:
  48. A[ k ] = mappedValue;
  49. }
  50. // d. Increase k by 1.
  51. k++;
  52. }
  53. // 9. return A
  54. return A;
  55. };
  56. }
时间: 2024-10-13 20:13:29

解惑 ["1", "2", "3"].map(parseInt) 为何返回[1,NaN,NaN]的相关文章

[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;].map(parseInt) 为何返回[1,NaN,NaN]

转载自:http://blog.csdn.net/freshlover/article/details/19034079 这涉及到是否深入理解两个函数的格式与参数含义. 首先根据我对两个函数用法的了解,猜测是由于parseInt(string, radix) 的参数radix(进制)必须介于2~36之间,而且字符串string中的每个位上的数字不能大于radix才能正确返回数字结果值. 我们通过以下javascript代码测试一下: var a=["1", "2",

[&#39;1&#39;,&#39;2&#39;,&#39;3&#39;].map(parseInt) 返回的是什么?

返回的是:[1,NaN,NaN] 首先我们先分析一下  parseInt  函数: parseInt()函数解析一个字符串参数,并返回指定基数的整数(数学系统中的基数). 它可以有两个参数,用法:parseInt(string, radix) string:要解析的值.如果其不是字符串,则将其转换为字符串(使用toString抽象操作).字符串开头的空白符将会被忽略. radix:可选.表示要解析的数字的基数.该值介于 2 ~ 36 之间,默认为10 返回值:返回解析后的整数值. 如果被解析参数

[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;].map(parseInt)?

["1", "2", "3"].map(parseInt)得到什么? 答案是:[1, NaN, NaN]. 原因:parseInt接收的是两个参数,map传递的是3个参数. map函数定义: arr.map(callback[,thisArg]); callback函数需要以下3个值: currentValue:当前处理数值 index:处理的数值的索引值 array:map函数处理的函数值 thisArg可选.  callback函数里的thi

[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;].map(parseInt) 答案是多少?

让我们先看看最直接最粗暴的方式 没错,答案就是:[1, NaN, NaN],那为什么答案是[1, NaN, NaN]呢? 1.让我们先了解一下map函数的定义 JavaScript Array map() 方法 定义和用法 map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值. map() 方法按照原始数组元素顺序依次处理元素. 注意: map() 不会对空数组进行检测. 注意: map() 不会改变原始数组. 因为 parseInt 需要两个参数 (val, radix

[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;].map(parseInt) 结果

// 下面的语句返回什么呢: ["1", "2", "3"].map(parseInt); // 你可能觉的会是[1, 2, 3] // 但实际的结果是 [1, NaN, NaN] // 通常使用parseInt时,只需要传递一个参数. // 但实际上,parseInt可以有两个参数.第二个参数是进制数. // 可以通过语句"alert(parseInt.length)===2"来验证. // map方法在调用callback

由[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;].map(parseInt) 引发的问题

基础知识 map语法 map(callback, [thisArg]) map 参数 callback 生成新数组元素的函数,callback参数,使用三个参数 currentValue callback 数组中正在处理的当前元素 index [可选] callback 数组中正在处理的当前元素的索引 array [可选] callback  map 方法被调用的数组 thisArg [可选] 执行 callback 函数时使用的this 值 返回值 一个新数组,每个元素都是回调函数的结果 pa

[&#39;1&#39;, &#39;2&#39;, &#39;3&#39;].map(parseInt) 输出答案和解析

根据题目可以了解到这道题主要考我们的是对map函数和parseInt函数的熟悉程序,所以我们先来了解这两个函数 map 根据MDN上对于map的解释:map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果. 上面的话读起来可能比较晦涩,我个人理解其实就是遍历数组,对数组的每一项进行遍历并做数据处理.这道题的关注重点就是在于map对于数组处理的方法,所以我们着重看下在MDN对于map参数的解释: callback 生成新数组的元素的函数,使用三个参数: curr

关于面试题:[1, 2, 3].map(parseInt)问题的剖析

一.前言 最近有小伙伴在公号中咨询了胡哥这道面试题,窃以为是比较有意思的一道面试题,于此分享给各位小伙伴.先把答案给了各位,和你理解的一样吗?! [1, 2, 3].map(parseInt) // [1, NaN, NaN] 如果你答案你都明白,请出门左转:React源码/原理了解一下. 二.剖析 这道面试题,本身并不复杂.不能正确回答问题的小伙伴,大多数集中于对parseInt这个函数的不了解或者了解的不全面,下面就由胡哥为大家抽丝剥茧一一讲述. 1. map函数 map()方法创建一个新数

parseInt在IE8转换返回不相等(parseInt(&quot;08&quot;)返回0等以0开头大于7的数字串)

描述 在IE8内核下parseInt("08")返回0,等以0开头大于7的数字串返回的值不相等 解决方法 parseInt当不指定radix时,当以0x开头时,s按照十六进制计算的:如果以0开头且第二位不为x,则s是按照八进制计算的,因为八进制不能有8,9所以报错返回0. 测试有效效果 parseInt("08",10)==8