kodingup.camp

Beranda/JavaScript Mastery: Object & Data

Konversi Nilai Antar Struktur

Modul 6 dari 144 menit bacaValue Conversion Between Structures

Isi modul

    Kenapa ini penting

    Data jarang datang dalam bentuk yang kamu inginkan. Input dari form HTML selalu berupa string, bahkan kalau pengguna mengetik angka. Data dari server datang sebagai teks JSON. Query string di URL berupa pasangan teks. Kamu harus terus-menerus mengubah data dari satu bentuk ke bentuk lain: string ke number, object ke array, array ke object, object ke teks JSON, dan sebaliknya.

    JavaScript juga punya kebiasaan mengubah tipe secara otomatis (type coercion) yang kadang membantu, kadang menjebak. Contoh terkenal: "5" + 3 menghasilkan "53", bukan 8. Kalau kamu menghitung total belanja dari input form tanpa konversi, kamu bisa mendapat total "10000020000" alih-alih 120000. Modul ini mengajarkan kapan JavaScript mengonversi sendiri, bagaimana mengonversi secara eksplisit dengan aman, dan alat untuk mengubah struktur data.

    Konsep inti

    Coercion implisit vs eksplisit

    Aturan penting operator +: kalau salah satu sisi string, + menjadi penggabungan teks. Operator lain (-, *, /, %) selalu mencoba mengubah ke angka.

    Konversi ke number

    Input Number(x) parseInt(x, 10) parseFloat(x)
    "42" 42 42 42
    " 42 " 42 42 42
    "12px" NaN 12 12
    "3.75" 3.75 3 3.75
    "" 0 NaN NaN
    null 0 NaN NaN
    undefined NaN NaN NaN
    true 1 NaN NaN

    Number() itu ketat: seluruh teks harus berupa angka valid. parseInt dan parseFloat itu longgar: membaca dari kiri sampai bertemu karakter yang bukan angka. Selalu beri argumen kedua 10 (radix/basis) pada parseInt supaya jelas kamu memakai basis desimal. Operator unary +x hasilnya sama dengan Number(x).

    Konversi ke boolean: truthy dan falsy

    Hanya ada sedikit nilai falsy (dianggap false): false, 0, -0, 0n, "", null, undefined, dan NaN. Semua yang lain truthy, termasuk "0", "false", [], dan {}. Ini sering mengejutkan pemula: array kosong itu truthy.

    Konversi ke string

    String(x) aman untuk semua nilai termasuk null dan undefined. Sebaliknya, x.toString() akan error kalau x bernilai null atau undefined. Template literal `${x}` juga mengonversi ke string.

    JSON: object ke teks dan sebaliknya

    JSON (JavaScript Object Notation) adalah format teks untuk bertukar data, dipakai hampir semua API web.

    Hal yang hilang atau berubah saat stringify: properti bernilai undefined, function, dan Symbol dibuang; NaN dan Infinity menjadi null; Date menjadi string ISO; Map dan Set menjadi {}. JSON.parse melempar SyntaxError jika teksnya tidak valid, jadi bungkus dengan try...catch saat memproses data dari luar.

    Mengubah struktur: entries, fromEntries, Array.from

    Contoh kode

    // 1) Coercion implisit
    console.log("5" + 3);      // → 53   (penggabungan teks)
    console.log("5" - 3);      // → 2    (konversi ke angka)
    console.log("5" * "2");    // → 10
    console.log(true + 1);     // → 2
    console.log([1, 2] + [3]); // → 1,23  (array diubah ke teks dulu)
    
    // 2) Input form selalu string: konversi dulu sebelum dihitung
    const hargaInput = "100000";
    const ongkirInput = "20000";
    console.log(hargaInput + ongkirInput);                 // → 10000020000 (salah)
    console.log(Number(hargaInput) + Number(ongkirInput)); // → 120000 (benar)
    
    // 3) Number vs parseInt vs parseFloat
    console.log(Number("12px"), parseInt("12px", 10), parseFloat("3.75kg")); // → NaN 12 3.75
    console.log(Number(""), Number(null), Number(undefined), Number(" 7 ")); // → 0 0 NaN 7
    console.log(parseInt("ff", 16), parseInt("101", 2)); // → 255 5
    
    // 4) Truthy dan falsy
    const nilaiUji = [0, "", "0", "false", [], {}, null, NaN];
    console.log(nilaiUji.map(Boolean).join(" "));
    // → false false true true true true false false
    
    // 5) String() aman, toString() bisa error
    console.log(String(null), String(undefined), String(123)); // → null undefined 123
    try {
      null.toString();
    } catch (err) {
      console.log(err.constructor.name); // → TypeError
    }
    
    // 6) JSON.stringify dan JSON.parse
    const pesanan = {
      id: 7,
      items: ["kopi", "roti"],
      catatan: undefined,
      hitung() {},
      dibuat: new Date(Date.UTC(2026, 0, 15)),
      rating: NaN,
    };
    const teks = JSON.stringify(pesanan);
    console.log(teks);
    // → {"id":7,"items":["kopi","roti"],"dibuat":"2026-01-15T00:00:00.000Z","rating":null}
    console.log(JSON.stringify({ a: 1, b: [2, 3] }, null, 2));
    // → {
    // →   "a": 1,
    // →   "b": [
    // →     2,
    // →     3
    // →   ]
    // → }
    
    const kembali = JSON.parse(teks);
    console.log(typeof kembali.dibuat); // → string (Date tidak otomatis kembali)
    
    // reviver untuk mengembalikan tanggal menjadi Date
    const denganDate = JSON.parse(teks, (kunci, nilai) => (kunci === "dibuat" ? new Date(nilai) : nilai));
    console.log(denganDate.dibuat.getUTCFullYear()); // → 2026
    
    // JSON tidak valid → SyntaxError
    try {
      JSON.parse("{nama: 'Budi'}"); // kunci & string wajib pakai kutip ganda
    } catch (err) {
      console.log(err.name); // → SyntaxError
    }
    
    // 7) Object.entries + Object.fromEntries untuk mengolah object
    const hargaRupiah = { kopi: 18000, teh: 12000, jus: 22000 };
    const naik10Persen = Object.fromEntries(
      Object.entries(hargaRupiah).map(([nama, harga]) => [nama, Math.round(harga * 1.1)])
    );
    // Math.round mencegah hasil seperti 13200.000000000002 (dibahas di modul 8)
    console.log(naik10Persen); // → { kopi: 19800, teh: 13200, jus: 24200 }
    
    const queryString = new URLSearchParams("q=sepatu&hal=2");
    console.log(Object.fromEntries(queryString)); // → { q: 'sepatu', hal: '2' }
    
    // 8) Array.from
    console.log(Array.from("halo"));                         // → [ 'h', 'a', 'l', 'o' ]
    console.log(Array.from(new Set([1, 1, 2, 3])));          // → [ 1, 2, 3 ]
    console.log(Array.from({ length: 5 }, (_, i) => i + 1)); // → [ 1, 2, 3, 4, 5 ]
    console.log(Array.from(new Map([["a", 1]])));            // → [ [ 'a', 1 ] ]
    

    Kesalahan umum

    1. Menjumlahkan input form tanpa konversi. Nilai dari <input> selalu string. Ubah dengan Number() sebelum dihitung, lalu cek hasilnya dengan Number.isNaN.
    2. Memakai parseInt tanpa radix atau untuk desimal. parseInt("3.75", 10) memotong menjadi 3. Untuk desimal pakai Number atau parseFloat.
    3. Mengira [] atau "0" falsy. Keduanya truthy. Untuk mengecek array kosong pakai arr.length === 0.
    4. Mengandalkan JSON.stringify untuk semua tipe. Date jadi string, Map/Set jadi {}, undefined dan function hilang. Konversi manual dulu atau pakai reviver saat parse.
    5. Memanggil JSON.parse tanpa try...catch pada data dari luar. Teks rusak akan melempar SyntaxError dan menghentikan program.

    Latihan

    1. Mudah, Diberikan array input ["15000", " 2500 ", "abc", ""]. Ubah semuanya dengan Number dan cetak hasilnya. Mana yang menjadi NaN, mana yang menjadi 0?
    2. Sedang, Buat function bacaJSON(teks) yang mengembalikan object hasil parse, atau null jika teks tidak valid.
    3. Menantang, Diberikan object nilai ujian { andi: 78, budi: 55, cici: 91, dodi: 60 }. Buat object baru yang hanya berisi siswa dengan nilai minimal 60, memakai Object.entries, filter, dan Object.fromEntries.
    Lihat solusi
    // 1) Mudah
    const input = ["15000", "  2500 ", "abc", ""];
    console.log(input.map(Number)); // → [ 15000, 2500, NaN, 0 ]
    // "abc" menjadi NaN, string kosong menjadi 0 (hati-hati!)
    
    // 2) Sedang
    function bacaJSON(teks) {
      try {
        return JSON.parse(teks);
      } catch {
        return null;
      }
    }
    console.log(bacaJSON('{"ok":true}')); // → { ok: true }
    console.log(bacaJSON("{rusak"));      // → null
    
    // 3) Menantang
    const nilai = { andi: 78, budi: 55, cici: 91, dodi: 60 };
    const lulus = Object.fromEntries(Object.entries(nilai).filter(([, skor]) => skor >= 60));
    console.log(lulus); // → { andi: 78, cici: 91, dodi: 60 }
    

    Ringkasan

    Kuis pemahaman

    Pilih satu jawaban per soal. Penjelasan muncul setelah kamu menjawab.