Kenapa ini penting
Setiap nilai di JavaScript punya tipe data. Tipe menentukan operasi apa yang bisa dilakukan: angka bisa dijumlahkan, teks bisa diubah ke huruf besar, daftar bisa diurutkan. Banyak bug pemula berasal dari salah tipe, misalnya "5" + 3 menghasilkan "53". Modul ini juga membahas satu konsep yang sering menjebak bahkan programmer berpengalaman: perbedaan by value dan by reference. Kalau kamu tidak paham ini, kamu bisa tanpa sengaja mengubah data di satu tempat dan kaget melihat data di tempat lain ikut berubah.
Konsep inti
Tujuh tipe primitif
Primitif adalah nilai tunggal yang sederhana dan tidak bisa diubah (immutable). JavaScript punya 7 tipe primitif:
| Tipe | Contoh | Keterangan |
|---|---|---|
string |
"Halo", 'JS', `Hai ${nama}` |
Teks |
number |
42, 3.14, -7, NaN, Infinity |
Angka (bulat maupun pecahan) |
bigint |
9007199254740993n |
Bilangan bulat sangat besar, diakhiri n |
boolean |
true, false |
Benar atau salah |
undefined |
undefined |
Variabel sudah ada tapi belum diberi nilai |
null |
null |
Sengaja dikosongkan oleh programmer |
symbol |
Symbol("id") |
Penanda unik, dipakai di kasus lanjutan |
Perbedaan undefined dan null sering membingungkan. Analogi kursi di bioskop: undefined itu kursi yang belum pernah dijual tiketnya (belum diisi sama sekali), sedangkan null itu kursi yang sengaja dikosongkan dengan tanda "kosong" (programmer secara sadar bilang "tidak ada nilai").
"Immutable" artinya nilainya sendiri tidak bisa diubah. "halo".toUpperCase() tidak mengubah string "halo". Method itu membuat string baru "HALO".
Tipe kompleks: object (termasuk array dan function)
Selain 7 primitif, semua yang lain adalah object. Object adalah wadah yang bisa menyimpan banyak nilai sekaligus.
- Object biasa: kumpulan pasangan key: value. Contoh
{ nama: "Ani", umur: 20 }. - Array: daftar berurutan yang diakses dengan index mulai dari 0. Contoh
["apel", "jeruk"]. - Function: blok kode yang bisa dipanggil (juga sejenis object).
- Lainnya:
Date,Map,Set, dan seterusnya.
Object bersifat mutable: isinya bisa diubah setelah dibuat.
Operator typeof
typeof mengembalikan string nama tipe sebuah nilai. Ada dua keanehan yang wajib diingat:
| Ekspresi | Hasil | Catatan |
|---|---|---|
typeof "hai" |
"string" |
|
typeof 42 |
"number" |
|
typeof NaN |
"number" |
NaN tetap bertipe number |
typeof 10n |
"bigint" |
|
typeof true |
"boolean" |
|
typeof undefined |
"undefined" |
|
typeof null |
"object" |
Bug bersejarah sejak JavaScript pertama, dipertahankan demi kompatibilitas |
typeof Symbol() |
"symbol" |
|
typeof {} |
"object" |
|
typeof [] |
"object" |
Array juga object. Pakai Array.isArray() untuk mengecek array |
typeof function(){} |
"function" |
By value vs by reference
Ini konsep terpenting di modul ini.
Primitif disalin by value. Saat kamu menulis let b = a, nilai a disalin ke b. Keduanya terpisah. Analogi: kamu memfotokopi selembar kertas lalu memberikannya ke teman. Kalau teman mencoret fotokopinya, kertas aslimu tetap bersih.
Object disalin by reference. Variabel object sebenarnya menyimpan alamat (referensi) ke lokasi object di memori. const b = a hanya menyalin alamatnya, jadi a dan b menunjuk ke object yang sama. Analogi: kamu memberi teman kunci duplikat rumahmu. Kalau teman memindahkan sofa, sofa di rumahmu juga pindah, karena rumahnya memang sama.
Akibatnya:
- Mengubah isi object lewat
bjuga terlihat lewata. - Dua object dengan isi sama tetap tidak sama kalau dibandingkan dengan
===, karena alamatnya berbeda:{} === {}hasilnyafalse. - Untuk membuat salinan terpisah, pakai spread
{ ...obj }/[...arr](salinan dangkal / shallow copy) ataustructuredClone(obj)(salinan dalam / deep copy, termasuk object di dalam object).
Contoh kode
// Tujuh primitif dan typeof
console.log(typeof "Halo"); // → string
console.log(typeof 3.14); // → number
console.log(typeof 10n); // → bigint
console.log(typeof false); // → boolean
console.log(typeof undefined); // → undefined
console.log(typeof null); // → object (bug bersejarah!)
console.log(typeof Symbol("id")); // → symbol
// Tipe kompleks
console.log(typeof { a: 1 }); // → object
console.log(typeof [1, 2, 3]); // → object
console.log(Array.isArray([1, 2, 3])); // → true
console.log(typeof function () {}); // → function
// undefined vs null
let alamat; // belum diisi
let nomorHp = null; // sengaja dikosongkan
console.log(alamat, nomorHp); // → undefined null
// Primitif immutable: method membuat nilai baru
const sapa = "halo";
const besar = sapa.toUpperCase();
console.log(sapa, besar); // → halo HALO
By value vs by reference:
// PRIMITIF: by value (disalin)
let a = 10;
let b = a;
b = 99;
console.log(a, b); // → 10 99 (a tidak ikut berubah)
// OBJECT: by reference (alamat yang disalin)
const user1 = { nama: "Ani", poin: 10 };
const user2 = user1; // user2 menunjuk object yang SAMA
user2.poin = 50;
console.log(user1.poin); // → 50 (user1 ikut berubah!)
// Perbandingan object membandingkan alamat
console.log({ x: 1 } === { x: 1 }); // → false
console.log(user1 === user2); // → true
// Salinan dangkal dengan spread
const user3 = { ...user1 };
user3.poin = 0;
console.log(user1.poin, user3.poin); // → 50 0
// Masalah salinan dangkal: object di dalam object masih berbagi referensi
const asli = { nama: "Budi", alamat: { kota: "Solo" } };
const dangkal = { ...asli };
dangkal.alamat.kota = "Klaten";
console.log(asli.alamat.kota); // → Klaten (ikut berubah)
// Salinan dalam dengan structuredClone
const asli2 = { nama: "Citra", alamat: { kota: "Solo" } };
const dalam = structuredClone(asli2);
dalam.alamat.kota = "Klaten";
console.log(asli2.alamat.kota); // → Solo (aman)
// Array juga by reference
const daftar = [1, 2, 3];
const salinan = [...daftar];
salinan.push(4);
console.log(daftar, salinan); // → [ 1, 2, 3 ] [ 1, 2, 3, 4 ]
Kesalahan umum
- Mengecek null dengan
typeof x === "null". Hasiltypeof nulladalah"object". Cek denganx === null. - Mengecek array dengan
typeof.typeof []bernilai"object". GunakanArray.isArray(x). - Mengira
const b = amembuat salinan object. Itu hanya menyalin referensi. Gunakan spread ataustructuredClone. - Mengira spread menyalin sampai ke dalam. Spread hanya menyalin satu tingkat. Untuk data bersarang, gunakan
structuredClone. - Membandingkan dua object atau array dengan
===.[1, 2] === [1, 2]bernilaifalse. Bandingkan isinya, misalnya elemen per elemen atau denganJSON.stringifyuntuk kasus sederhana.
Latihan
- Mudah, Buat satu variabel untuk masing-masing tipe primitif (7 variabel), lalu cetak
typeofsetiap variabel. - Sedang, Buat function
tipeAsli(x)yang mengembalikan"null"untuk null,"array"untuk array, dan hasiltypeofbiasa untuk yang lain. - Menantang, Diberikan
const produk = { nama: "Kaos", harga: 80000, varian: ["S", "M"] }. Buat salinan bernamaprodukBarudengan harga 90000 dan varian ditambah"L", tanpa mengubahprodukasli sedikit pun. Buktikan denganconsole.log.
Lihat solusi
1.
const s = "teks";
const n = 7;
const big = 7n;
const bool = true;
let u;
const kosong = null;
const sym = Symbol("kunci");
for (const nilai of [s, n, big, bool, u, kosong, sym]) {
console.log(typeof nilai);
}
// → string, number, bigint, boolean, undefined, object, symbol (satu per baris)
2.
function tipeAsli(x) {
if (x === null) return "null";
if (Array.isArray(x)) return "array";
return typeof x;
}
console.log(tipeAsli(null)); // → null
console.log(tipeAsli([1])); // → array
console.log(tipeAsli({})); // → object
console.log(tipeAsli("a")); // → string
3.
const produk = { nama: "Kaos", harga: 80000, varian: ["S", "M"] };
const produkBaru = {
...produk,
harga: 90000,
varian: [...produk.varian, "L"], // array baru, bukan referensi lama
};
console.log(produk); // → { nama: 'Kaos', harga: 80000, varian: [ 'S', 'M' ] }
console.log(produkBaru); // → { nama: 'Kaos', harga: 90000, varian: [ 'S', 'M', 'L' ] }
Kalau kamu menulis produkBaru.varian.push("L") setelah spread biasa, array varian milik produk juga ikut bertambah, karena keduanya berbagi array yang sama.
Ringkasan
- Ada 7 primitif: string, number, bigint, boolean, undefined, null, symbol. Selain itu semuanya object (termasuk array dan function).
typeof nullmenghasilkan"object"(bug bersejarah) dantypeof []juga"object". Pakaix === nulldanArray.isArray.- Primitif disalin by value, object disalin by reference (alamatnya).
{} === {}bernilaifalsekarena yang dibandingkan adalah alamat.- Spread (
{...o},[...a]) membuat salinan dangkal,structuredClonemembuat salinan dalam.