解惑 [1, 2, 3].map(parseInt) 为何返回[1,NaN,NaN]
javascript中的parseInt與map函數都是常用的函數,可是?["1", "2", "3"].map(parseInt) 為何返回不是[1,2,3]卻是[1,NaN,NaN]?
這涉及到是否深入理解兩個函數的格式與參數含義。
首先根據我對兩個函數用法的了解,猜測是由于parseInt(string,?radix) 的參數radix必須介于2~36之間,而且字符串string中的數字不能大于radix才能正確返回數字結果值。
我們通過以下javascript代碼測試一下:
?
[javascript]?view plaincopy?
返回結果為:[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-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?方法的用法。
//?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,4map?方法可應用于字符串。?下面的示例闡釋了這一點。
//?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, 2, 3].map(parseInt) 为何返回[1,NaN,NaN]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过ip快速定位问题主机连接的交换机
- 下一篇: 排序算法大集锦_合并排序_1(分治思想)