ParseInt neden Array # haritasıyla NaN verir?


291

Gönderen Mozilla Geliştirici Ağı :

[1,4,9].map(Math.sqrt)

verim:

[1,2,3]

O zaman bunu neden yapar:

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

bunu ver:

[1, NaN, NaN]

Firefox 3.0.1 ve Chrome 0.3'te test ettim ve sadece bir feragatname olarak, bu tarayıcılar arası işlev olmadığını biliyorum (IE yok).

Aşağıdakilerin istenen etkiyi gerçekleştireceğini öğrendim. Ancak, hala hatalı davranışını açıklamamaktadır parseInt.

['1','2','3'].map(function(i){return +i;}) // returns [1,2,3]

15
Tembel için: kullanın .map(parseFloat)çünkü bir parametre alır.

63
Veya kullanın .map(Number).
Nikolai

2
elle yuvarlanma işlevi olmayan tamsayılar istiyorsanız arr.map (Math.floor) kullanabilirsiniz.
dandavis

@ Nikolai user669677 harika öneriler! Bir anwser
BiAiB

Herkes
parseInt

Yanıtlar:


478

İçinde geri çağırma işlevi Array.mapvardır üç parametre:

Aynı itibaren Mozilla sayfasından size bağlı olduğunu:

geri çağrı üç bağımsız değişkenle çağrılır: öğenin değeri, öğenin dizini ve çapraz kullanılan Array nesnesi. "

Dolayısıyla, parseIntaslında iki bağımsız değişken bekleyen bir işlev çağırırsanız , ikinci bağımsız değişken öğenin dizini olur.

Bu durumda, parseIntsırayla 0, 1 ve 2 yarıçapı ile arama yaptınız . Birincisi parametreyi vermemekle aynıdır, bu nedenle girişe göre varsayılan olarak ayarlanmıştır (bu durumda taban 10). Taban 1, imkansız bir sayı tabanıdır ve 3, taban 2'deki geçerli bir sayı değildir:

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 

Bu durumda, sarma işlevine ihtiyacınız var:

['1','2','3'].map(function(num) { return parseInt(num, 10); });

veya ES2015 + sözdizimi ile:

['1','2','3'].map(num => parseInt(num, 10));

(Her iki durumda da, gösterildiği gibi bir yarıçapı açıkça belirtmek en iyisidir parseInt, aksi takdirde girdiye dayalı olarak yarıçapı tahmin eder. Bazı eski tarayıcılarda, önde gelen 0, sekizlik tahmin etmesine neden oldu, bu da sorunlu olma eğilimindeydi. dize ile başlıyorsa hex'i tahmin edin 0x.)


25

mapikinci bir argümandan geçiyor (ki bu çoğu durumda) parseIntsayı tabanı grafiğini bozuyor.

Alt çizgi kullanıyorsanız şunları yapabilirsiniz:

['10','1','100'].map(_.partial(parseInt, _, 10))

Veya alt çizgi olmadan:

['10','1','100'].map(function(x) { return parseInt(x, 10); });


18

Kullanarak bu sorunu çözebilir Numarası iteratee fonksiyonu olarak:

var a = ['0', '1', '2', '10', '15', '57'].map(Number);

console.log(a);

Yeni işleç olmadan, sayı tür dönüştürme gerçekleştirmek için kullanılabilir. Ancak, parseInt'den farklıdır: dizeyi ayrıştırmaz ve sayı dönüştürülemezse NaN değerini döndürür. Örneğin:

console.log(parseInt("19asdf"));
console.log(Number("19asf"));


11

Ben parseInt's 2. parametre, sayı tabanı ile devam eden korkak bir şey bahis olacak. Neden doğrudan aradığınızda değil, Array.map kullanımı ile kırılıyor, bilmiyorum.

//  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 ) } );

1
parseInt yalnızca, verilen dize 0 karakterle başlıyorsa sekizlik kabul eder.
Alnitak

Oh ya ... bu doğru. Girdiye dayalı olarak yarıçapı "tahmin etmeye" çalışır. Bunun için üzgünüm.
Peter Bailey

3

ES2015 / ES6 ok işlevini kullanabilir ve yalnızca parseInt öğesine sayı iletebilirsiniz. Sayı tabanı için varsayılan değer 10 olacaktır

[10, 20, 30].map(x => parseInt(x))

Ya da kodunuzun daha iyi okunabilmesi için açık alan belirtebilirsiniz.

[10, 20, 30].map(x => parseInt(x, 10))

Örnekte yukarıdaki sayı tabanı açıkça 10 olarak ayarlanmıştır


1

başka bir (çalışan) hızlı düzeltme:

var parseInt10 = function(x){return parseInt(x, 10);}

['0', '1', '2', '10', '15', '57'].map(parseInt10);
//[0, 1, 2, 10, 15, 57]

0

parseIntBu nedenle IMHO'dan kaçınılmalıdır. Aşağıdaki gibi bağlamlarda daha güvenli hale getirmek için sarabilirsiniz:

const safe = {
  parseInt: (s, opt) => {
    const { radix = 10 } = opt ? opt : {};
    return parseInt(s, radix);
  }
}

console.log( ['1','2','3'].map(safe.parseInt) );
console.log(
  ['1', '10', '11'].map(e => safe.parseInt(e, { radix: 2 }))
);

lodash / fp bu gotcha'lardan kaçınmak için varsayılan olarak 1 yineleme argümanını sınırlar. Şahsen ben kaçınmak kadar çok hata oluşturmak için bu geçici çözümler bulduk. Daha parseIntgüvenli bir uygulama lehine kara liste yapmak bence daha iyi bir yaklaşımdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.