Lekcja 5 Zmiana typu wartości

JavaScript często automatycznie zmienia typy (tzw. coercion), ale masz też narzędzia do jawnej konwersji.
Warto znać oba światy, żeby uniknąć niespodzianek.

Sprawdzanie typu: typeof

typeof 2;                 // "number"
typeof "2";               // "string"
typeof true;              // "boolean"
typeof undefined;         // "undefined"
typeof null;              // "object"      // historyczny „babolek”
typeof {};                // "object"
typeof [];                // "object"      // tablice to obiekty
typeof function(){};      // "function"
typeof 10n;               // "bigint"
typeof Symbol("id");      // "symbol"
Number.isNaN(NaN);        // true (zamiast isNaN, które konwertuje argumenty)

Uwaga: typeof null === "object" – to znany błąd kompatybilności, z którym żyje cały ekosystem.


Tekst → liczba

Niejawna konwersja (coercion)

  • Operator *, /, - próbują konwertować do liczby:

"2" * 1;        // 2
"10" - 3;       // 7
"6" / "2";      // 3
  • Uwaga na +: jest zarówno „dodawaniem”, jak i „łączeniem tekstu” – jeśli którykolwiek operand jest stringiem, wynik staje się stringiem:

"2" + 1;        // "21"  (łączenie tekstu!)

Jawna konwersja

Najczytelniejsze i najbezpieczniejsze:

Number("2");       // 2
parseInt("101", 2) // 5  (drugi argument to podstawa systemu)
parseFloat("3.14") // 3.14
+"2"               // 2   (unarny plus – krótko, ale mniej czytelnie)

Pułapki:

Number("2a");      // NaN
parseInt("2a");    // 2    (czyta do pierwszego nieliczbowego znaku)
parseInt("08");    // 8    (w nowoczesnym JS OK, kiedyś bywały kłopoty z 0-wiodącym)

Liczba → tekst

Niejawna konwersja

2 + "";                // "2"
`${2}`;                // "2" (template literal)

Jawna konwersja

String(2);             // "2"
(2).toString();        // "2"
(255).toString(16);    // "ff"  (do innego systemu liczbowego)

„Binarka” ↔ tekst (ASCII/Unicode)

Najczęściej „binarka” to ciąg bitów reprezentujący kod znaku (np. ASCII).
Przykład: zamiana łańcucha binarnego na tekst (po znaku):

// Binarny zapis „Hi” (H=72 -> 1001000, i=105 -> 1101001)
const bins = ["1001000", "1101001"];
const chars = bins
  .map(b => String.fromCharCode(parseInt(b, 2)))
  .join("");
// chars === "Hi"

Tekst → binarka (po znakach, z 8-bitowym wyrównaniem):

const text = "Hi!";
const bin = [...text]
  .map(ch => ch.charCodeAt(0).toString(2).padStart(8, "0"))
  .join(" "); 
// "01001000 01101001 00100001"

Dla znaków poza ASCII (np. polskie litery) wchodzimy w temat Unicode/UTF-8 – wtedy „binarka” nie zawsze równa się „8 bitów na znak”. Do kodowań bajtowych warto użyć TextEncoder/TextDecoder:

const enc = new TextEncoder();            // UTF-8
const bytes = enc.encode("Żółć");         // Uint8Array bajtów
const dec = new TextDecoder("utf-8");
dec.decode(bytes);                         // "Żółć"

Tekst z liczb w różnych systemach

parseInt("ff", 16);        // 255
(255).toString(2);         // "11111111"
parseInt("11111111", 2);   // 255

Na Boolean (prawda/fałsz)

Boolean(0);        // false
Boolean("");       // false
Boolean(null);     // false
Boolean(undefined);// false
Boolean(NaN);      // false
Boolean("0");      // true   (niepusta wartość)
Boolean([]);       // true
Boolean({});       // true
!!"tekst";         // true   (podwójna negacja = szybkie rzutowanie)

BigInt i inne typy

BigInt("9007199254740993");  // 9007199254740993n
10n + 20n;                   // 30n
// Uwaga: nie mieszamy BigInt z Number bez jawnej konwersji:
Number(10n) + 5;             // 15

Typowe „gotowce”

Tekst → liczba

const n1 = Number(str);
const n2 = +str;
const n3 = parseInt(str, 10);    // jeśli to liczba całkowita w zapisie dziesiętnym
const n4 = parseFloat(str);      // jeśli może mieć część ułamkową

Liczba → tekst

const s1 = String(num);
const s2 = num + "";
const s3 = `${num}`;
const hex = num.toString(16);

Binarka ↔ liczba ↔ tekst

const num = parseInt(binStr, 2);
const binStr2 = num.toString(2);
const ch = String.fromCharCode(num);

Sprawdzanie typów

typeof x;                // szybki podgląd typu prymitywu/obiektu
Array.isArray(x);        // tablice
x === null;              // null-guard
Number.isNaN(x);         // poprawne sprawdzenie NaN

Najczęstsze pułapki i jak ich uniknąć

  1. + łączy tekst
    Jeśli którykolwiek operand jest stringiem, wynik będzie stringiem. Do liczb używaj Number(), parse* lub operatorów *, -, /.

  2. parseInt vs Number
    Number("12px") → NaN, ale parseInt("12px", 10) → 12. Wybierz właściwe narzędzie.

  3. NaN
    NaN !== NaN. Sprawdzaj Number.isNaN(x).

  4. typeof null
    Zwraca "object". Do sprawdzenia null używaj x === null.

  5. Unicode a „binarka”
    Dla znaków spoza ASCII stosuj TextEncoder/TextDecoder.


Mini-ściąga (1 ekran)

// sprawdzenie typu
typeof x; Array.isArray(x); x === null; Number.isNaN(x);

// tekst -> liczba
Number("42"); +("42"); parseInt("101", 2); parseFloat("3.14");

// liczba -> tekst
String(42); 42 + ""; `${42}`; (255).toString(16);   // "ff"

// bool
Boolean(val); !!val;

// binarka <-> liczba <-> znak
parseInt("01100001", 2);              // 97
String.fromCharCode(97);              // "a"
(97).toString(2).padStart(8, "0");    // "01100001"

// UTF-8 bajty <-> tekst
const enc = new TextEncoder();
const dec = new TextDecoder("utf-8");
const bytes = enc.encode("Żółć");
dec.decode(bytes);                    // "Żółć"

Masz to! Jeśli chcesz, przerobię to na gotowy wpis HTML (albo Markdown) pod Twojego bloga, z blokami <pre><code> i wyróżnieniami.

Zostaw komentarz

Koszyk