Przejdź do głównej zawartości

Bug #083

🪲 Znajdź buga

console.log(typeof NaN)

console.log(isNaN("foo"))
console.log(Number.isNaN("foo"))

console.log(isNaN(() => {}))
console.log(Number.isNaN(() => {}))

console.log(isNaN({}))
console.log(Number.isNaN({}))

console.log(isNaN([1, 2]))
console.log(Number.isNaN([1, 2]))

console.log(isNaN(undefined))
console.log(Number.isNaN(undefined))

console.log(isNaN(NaN))
console.log(isNaN("NaN"))

console.log(isNaN(123))
console.log(isNaN("123"))
console.log(isNaN([]))
console.log(isNaN(true))
console.log(isNaN(false))
console.log(isNaN(null))

Jakie wartości zostaną zalogowane do konsoli?

🧪 Rozwiązanie

console.log(typeof NaN) // number

console.log(isNaN("foo")) // true
console.log(Number.isNaN("foo")) // false

console.log(isNaN(() => {})) // true
console.log(Number.isNaN(() => {})) // false

console.log(isNaN({})) // true
console.log(Number.isNaN({})) // false

console.log(isNaN([1, 2])) // true
console.log(Number.isNaN([1, 2])) // false

console.log(isNaN(undefined)) // true
console.log(Number.isNaN(undefined)) // false

console.log(isNaN(NaN)) // true
console.log(isNaN("NaN")) // true

console.log(isNaN(123)) // false
console.log(isNaN("123")) // false (?)
console.log(isNaN([])) // false (?!)
console.log(isNaN(true)) // false (?!)
console.log(isNaN(false)) // false (?!)
console.log(isNaN(null)) // false (?!)

Po pierwsze isNaN() i Number.isNaN() nie są ze sobą zgodne 🤯.

Teoretycznie założeniem isNaN() jest sprawdzenie czy wartość przekazana w argumencie nie jest wartością liczbową.

W praktyce isNaN() sprawdza jednak czy wartość z argumentu jest ekwiwalentna wartości NaN po konwersji do wartości liczbowej.

Co więcej, dokumentacja Mozilli zachęca do korzystania z Number.isNaN() jako bardziej niezawodnego odpowiednika.

Tak, isNan() i Number.isNaN() potrafią zwracać różną wartość dla tego samego argumentu wejściowego.

Mimo deklarowanej większej niezawodności, Number.isNaN() wciąż jest bardzo nieintuicyjną metodą w celu sprawdzania, czy wartość wejściowa nie jest wartością liczbową.

Dla uzyskania niezawodności i intuicyjności najlepiej skorzystać z porównania typeof x === "number".

Mamy wtedy pewność, że dostaniemy true tylko wtedy, gdy x będzie typu liczbowego.

Pułapką może okazać się wtedy typeof NaN === "number", który zwróci true, ponieważ typ wartości NaN to... number.

Największe (moim zdaniem) pułapki w kwesti isNaN() i Number.isNaN() (gdy są ze sobą zgodne), to:

  • Sprawdzanie ciągu znaków, który zawiera liczbę np. "123"
  • Pustej tablicy []
  • Wartości logicznych true/false
  • null

Wszystkie z powyższych wartości ulegają konwersji do wartości liczbowych.

Ciąg znaków "123" zostaje skonwertowany do wartości liczbowej 123 więc isNaN("123"), tak samo jak Number.isNaN("123"), zwraca false.

Pusta tablica również jest konwertowana do wartości liczbowej, 0.

Wartości logiczne true/false są konwertowane do 1/0.

null również ulega konwersji do wartości 0.

Z tego względu, powyższe wartości po konwersji do wartości liczbowej nie stają się wartością NaN, więc isNaN() dla nich zwraca false.

🎢 Plac zabaw

Otwórz edytor w nowym oknie

📑 Linki

❤️ Podobają Ci się bugi JS?

Podziel się linkiem ze znajomymi:
https://codisity.pl/100-bugow-js