Porovnání skoro-čísel

AndreaAndrea

Předvedeme si trochu trochu matoucí kod, ve kterém porovnává dva různé typy dat: číslo a pole. Tipnete správně jestli se podmínka vyhodnotí na true nebo false?

if (32 == [32]) {
	// true?
} else {
	// false?
}

Pokud si nejste jistí, vysvětlíme si krok za krokem, jak JS dojde k odpovědi.

Primitivní datový typ a pole

Pro správné porovnání musíme nejprve dojít ke stejnému datovému typu, protože počítač neumí porovnat jabka a hrušky. Při použití dvojitého rovná se == se provádí typové konverze, která vyhodnotí jako největší problém, že porovnáváme pole a primitivní hodnotu. Pole tedy pomocí abstraktní operace toPromitive, převede daný objekt na jeho primitivní hodnotu, která může být použita k porovnání s druhým operandem. Dochází k automatické konverzi pole na řetězec, protože je volána metoda toString() v rámci metody ToPrimitive(). Tento řetězec je pak porovnán s číslem pomocí operátoru == a dostáváme:

if (32 == "32") {
	// true?
} else {
	// false?
}

Porovnání primitivních datových typů

V tomto konkrétním případě už je vidět, že pravděpodobným výsledkem bude true, protože řetězec "42" se při porovnání s číslem 42 vyhodnotí jako číslo 42. Pokud máme na obou stranách stejný datový typ, tak se operátor dvojité a trojité rovná se chová identicky.

if (32 === 32) {
	// true?
} else {
	// false?
}

Nakonec si můžeme představit, že ještě dochází k finální konverzi na boolean, kterou se řídí podmínka if.

Závěrem

Tento příklad ukázkou, proč koerze může být špatná věc. Tento JS kód může být trochu matoucí a provádí na pozadí mnoho věcí. Problém kódu je, že v první řadě děláte nesmyslné porovnání.

Změna na trojité rovná se, by problém nevyřešilo a změnila by funkčnost kódu. Pokud děláte smysluplné porovnání, například srovnáváte řetězec s číslem, může dávat použití dvojitého rovná se naprostý smysl.