Přejít k navigační liště

Zdroják » Zprávičky » Když osm není osm: Pozor na vyhodnocování čísel v JavaScriptu

Když osm není osm: Pozor na vyhodnocování čísel v JavaScriptu

Představte si, že ošetříte pole ve formuláři na webové stránce pomocí JavaScriptu tak, aby uživatel musel zadat celé číslo větší než nula. Jako příklad si můžeme vzít třeba pole pro zadání měsíce (1–12). Abyste uživateli ušetřili práci, vyhodnotíte vložený údaj pomocí parseInt() a pokud bude hodnota mimo zadaný interval, nedovolíte formulář odeslat. Jde o jednoduchou funkci, každý ji bez problémů dokáže napsat, při testech vše funguje tak jak má, až při předání zákazníkovi se začnou množit stížnosti na to, že nelze odeslat formulář, i když je všechno vyplněné správně.

Možná příčina je ve funkci parseInt. Schválně, zkuste si tipnout, co v JavaScriptu vypíše následující kód:

function test(x) {
    document.write("'" + x + "' = ");
    document.write(parseInt(x));
    document.write("

");
}
test("01");
test("02");
test("07");
test("08");
test("09");

Možná vás to překvapí (i když by nemělo!), ale výsledek bude vypadat takto:

'01' = 1
'02' = 2
'07' = 7
'08' = 0
'09' = 0

(Můžete si otestovat)

Stačí pak, aby uživatel do pole pro měsíc nezadal „8“, ale „08“, a bude chováním velmi překvapen (navíc když mu zadání „07“ prošlo bez problémů…) Příčina je, jak už jistě tušíte, v tom, že JS parser používá syntaxi čísel z C, kde číslo, které začíná znakem „0“, je zapsáno v osmičkové soustavě.

Jak se vyhnout podobným problémům, a to rovnou několika různými způsoby, ukazuje Thomas Fuchs v článku Adventures in JavaScript number parsing.

Komentáře

Subscribe
Upozornit na
guest
6 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
kkl2401

Ono je to trochu složitější, jak člověk ostatně zjistí, když si zmíněnou ukázku vyzkouší ve větším množství prohlížečů; například v Opeře to dopadne „dobře“.
Ve skutečnosti je to tak, že soucasna specifikace ECMA-262 (http://www.ecma-international.org/publications/standards/Ecma-262.htm) ve sve pate edici jasne hovori o tom, ze pokud funkci parseInt neni druhy parametr (ciselna soustava) predan a pokud retezec nezacina (az na bile znaky) „0X“ (nebo „0ד), bere se jako ciselna soustava ta desitkova. Predchozi, treti edice, hovorila o tom, ze pripady zminene ve zpravicce prohlizec muze (ale nemusi!) interpretovat jako oktalova cisla. Podobne o tom mluvi popis JavaScriptu 1.5 (https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/parseInt): „If the input string begins with „0“, radix is eight (octal). Although widespread, this feature is specified as implementation dependent; always use a base for consistent results.“
Jinymi slovy kazdopadne je rozumne vzdy druhy parametr uvest, nicmene neni pravda to, ze kdyz to clovek neudela, tak budou ta cisla vsude vnimana oktalove, ani na to se nelze spolehat.

spud

Zajímavé, s tím jsem se ještě nesetkal a asi by mě to docela zaskočilo (už v JS dlouho nedělám). Dřív jsem ale většinou používal alternativní převody na číslo – vynásobením 1, na string – přičtením prázdného znaku.
Když jsem zkusil příklad z články upravit „po staru“ tak to fungovalo jak mělo.
var x = ‚08‘;
var y = x * 1;
document.write(„‚“+ x +“‘ = “ + y);
vysledek je ‚08‘ = 8

šachy

Ono by to šlo obejít také podmínkou
if(x.charAt(0)==„0“)
x=x.substring(1,x­.length)
Ikdyž souhlasím že nejjednodušší je vynásobení *1.

KarelI

Prominte, ale to je vzorova takyoprava od takyprogramatora, ktery nejdriv pise a pak mozna premysli. Takovych pripadu je na http://thedailywtf.com mraky. Co se stane, kdyz tech nul bude vic nebo kdyz tam bude mezera?

DevelX

Existuje jednoduché riešenie: použiť druhý argument, ktorý vynúti zvolenú číselnú sadu, takže potom sa parseInt(‚09‘, 10) vyhodnotí ako 9.

100% Lenin

Tak to dělá skutečný programátor a ne slizovač smetánky :D

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.