javascript - Hvorfor gir parseInt NaN med Array#map?
Fra Mozilla Developer Network:
[1,4,9].map(Math.sqrt)
vil gi:
[1,2,3]
Hvorfor gjør da dette:
['1','2','3'].map(parseInt)
gi dette:
[1, NaN, NaN]
Jeg har testet i Firefox 3.0.1 og Chrome 0.3, og bare som en ansvarsfraskrivelse, jeg vet at dette ikke er funksjonalitet på tvers av nettlesere (ingen IE).
Jeg fant ut at følgende vil oppnå ønsket effekt. Imidlertid forklarer det fortsatt ikke den feilaktige oppførselen til parseInt.
['1','2','3'].map(function(i){return +i;}) // returns [1,2,3]
Svar #1
Tilbakekallingsfunksjonen i Array.map har tre parametere:
Fra den samme Mozilla-siden som du lenket til:
tilbakeroppsfunksjonen kalles med tre argumenter: verdien av elementet, indeksen til elementet, og Array-objektet som blir gjennomgått.
Så hvis du kaller en funksjon parseInt som faktisk forventer to argumenter, vil det andre argumentet være indeksen til elementet.
I dette tilfellet endte du opp med å kalle parseInt med radix 0, 1 og 2 etter tur. Den første er det samme som å ikke oppgi parameteren, så den ble satt til standard basert på inngangen (base 10, i dette tilfellet). Base 1 er en umulig tallbase, og 3 er ikke et gyldig tall i base 2:
parseInt('1', 0); // OK - gives 1
parseInt('2', 1); // FAIL - 1 isn't a legal radix
parseInt('3', 2); // FAIL - 3 isn't legal in base 2
Så i dette tilfellet trenger du wrapper-funksjonen:
['1','2','3'].map(function(num) { return parseInt(num, 10); });
eller med ES2015+ syntaks:
['1','2','3'].map(num => parseInt(num, 10));
(I begge tilfeller er det best å uttrykkelig oppgi en radix til parseInt som vist, fordi ellers gjetter den radix basert på input. I noen eldre nettlesere forårsaket en ledende 0 at den gjettet oktal, noe som ofte var problematisk. Den vil fortsatt gjette heksadesimal hvis strengen begynner med 0x.)
Svar #2
map sender med et andre argument, som (i mange tilfeller) roter til parseInt's radix-parameter.
Hvis du bruker underscore, kan du gjøre:
['10','1','100'].map(_.partial(parseInt, _, 10))Eller uten understrek:
['10','1','100'].map(function(x) { return parseInt(x, 10); });Svar #3
Du kunne løse dette problemet ved å bruke Number som iterasjonsfunksjon:
var a = ['0', '1', '2', '10', '15', '57'].map(Number);
console.log(a);Uten den nye operatoren kan Number brukes til å utføre typekonvertering. Den skiller seg imidlertid fra parseInt: den analyserer ikke strengen og returnerer NaN hvis tallet ikke kan konverteres. For eksempel:
console.log(parseInt("19asdf"));
console.log(Number("19asf"));Svar #4
Jeg vil tippe at det er noe rart som skjer med parseInts andre parameter, radix. Hvorfor det bryter når man bruker Array.map og ikke når man kaller det direkte, vet jeg ikke.
// Works fine
parseInt( 4 );
parseInt( 9 );
// Breaks! Why?
[1,4,9].map( parseInt );
// Fixes the problem
[1,4,9].map( function( num ){ return parseInt( num, 10 ) } );
