Bab 3: Objek — Dasar

8 menit baca

Sampai sini kamu udah kenal tipe data primitif: string, number, boolean, dll. Sekarang kita masuk ke dunia objek — tipe data yang jauh lebih powerful dan jadi fondasi hampir semua hal di JavaScript.


3.1 Objek (Objects)

Apa Itu Objek?

Kalau primitif itu kayak satu lembar catatan (cuma simpan satu nilai), objek itu kayak lemari arsip — bisa simpan banyak data sekaligus, masing-masing punya label (nama).

javascript
// Lemari arsip bernama "user"
const user = {
  nama: "Budi",
  umur: 25,
  sudahMenikah: false
};

Setiap data di dalam objek disebut property (properti). Formatnya: kunci: nilai.

Membuat Objek

Ada 2 cara:

javascript
// 1. Object literal (PALING UMUM — pakai ini)
const mobil = {
  merk: "Toyota",
  tahun: 2020
};

// 2. Object constructor (jarang dipakai)
const mobil2 = new Object();
mobil2.merk = "Honda";

Mengakses Properti

javascript
const user = {
  nama: "Budi",
  umur: 25
};

// Dot notation (paling sering)
console.log(user.nama); // "Budi"

// Bracket notation (untuk nama properti yang "aneh")
console.log(user["umur"]); // 25

Kapan pakai bracket? Kalau nama properti-nya:

  • Mengandung spasi: user["suka makan"]
  • Dari variabel: user[kunciDariVariabel]
  • Mengandung karakter spesial
javascript
const user = {
  "suka kucing": true
};

// Ini ERROR:
// console.log(user.suka kucing);

// Ini BENAR:
console.log(user["suka kucing"]); // true

// Dari variabel:
const kunci = "suka kucing";
console.log(user[kunci]); // true

Menambah, Mengubah, Menghapus Properti

javascript
const user = {
  nama: "Budi"
};

// Tambah properti baru
user.umur = 25;
user.kota = "Jakarta";

// Ubah properti
user.nama = "Andi";

// Hapus properti
delete user.kota;

console.log(user); // { nama: "Andi", umur: 25 }

Kok const tapi bisa diubah? Karena const cuma menjaga agar variabel user tidak bisa di-reassign ke objek lain. Isi di dalamnya tetap bisa diubah. Analoginya: alamat rumah tetap, tapi furniture di dalam rumah boleh diganti.

Computed Properties

Nama properti bisa diambil dari variabel saat membuat objek:

javascript
const kunci = "warna";

const tas = {
  [kunci]: "merah" // sama dengan: warna: "merah"
};

console.log(tas.warna); // "merah"

Property Shorthand

Kalau nama variabel sama dengan nama properti, bisa disingkat:

javascript
const nama = "Budi";
const umur = 25;

// Cara panjang:
const user1 = { nama: nama, umur: umur };

// Cara singkat (shorthand):
const user2 = { nama, umur };

// Hasilnya sama!
console.log(user2); // { nama: "Budi", umur: 25 }

Mengecek Properti Ada atau Tidak

javascript
const user = { nama: "Budi", umur: 25 };

// Cara 1: Bandingkan dengan undefined
console.log(user.alamat === undefined); // true (tidak ada)

// Cara 2: Operator "in" (LEBIH AMAN)
console.log("nama" in user);   // true
console.log("alamat" in user); // false

Kenapa in lebih aman? Karena ada kasus langka di mana properti memang sengaja diisi undefined:

javascript
const obj = { test: undefined };

console.log(obj.test === undefined); // true — seolah tidak ada
console.log("test" in obj);         // true — padahal ADA!

Perulangan for...in

Untuk menelusuri semua properti objek:

javascript
const user = {
  nama: "Budi",
  umur: 25,
  kota: "Jakarta"
};

for (let kunci in user) {
  console.log(`${kunci}: ${user[kunci]}`);
}
// nama: Budi
// umur: 25
// kota: Jakarta

⚠️ Jebakan: Urutan Properti

Properti dengan nama angka bulat akan diurutkan secara otomatis (ascending). Properti lain muncul sesuai urutan pembuatan.

javascript
const kodeNegara = {
  "62": "Indonesia",
  "1": "USA",
  "81": "Jepang"
};

for (let kode in kodeNegara) {
  console.log(kode); // "1", "62", "81" — BUKAN urutan asli!
}

// Trik: tambahkan "+" di depan agar tidak dianggap integer
const kodeNegara2 = {
  "+62": "Indonesia",
  "+1": "USA",
  "+81": "Jepang"
};
🎯Challenge

Buat objek buku dengan properti: judul, penulis, tahun, sudahDibaca. Lalu:

  1. Tambahkan properti genre
  2. Ubah sudahDibaca jadi true
  3. Hapus properti tahun
  4. Tampilkan semua properti dengan for...in

3.2 Referensi Objek dan Penyalinan

Primitif vs Objek: Perbedaan Fundamental

Ini konsep yang SANGAT PENTING dan sering bikin bingung pemula.

Primitif disalin berdasarkan nilai (copy):

javascript
let pesan = "Halo";
let salinan = pesan; // salinan dapat COPY-nya

salinan = "Bye";
console.log(pesan); // "Halo" — tidak berubah!

Objek disalin berdasarkan referensi (alamat):

javascript
let user = { nama: "Budi" };
let admin = user; // admin dapat ALAMAT yang sama!

admin.nama = "Andi";
console.log(user.nama); // "Andi" — IKUT BERUBAH!
💡Analogi

Bayangkan objek itu rumah, dan variabel itu kartu nama yang berisi alamat rumah.

  • let admin = user → kamu fotokopi kartu nama (alamat sama, rumah sama)
  • Kalau admin renovasi rumah, user juga lihat perubahan — karena rumahnya SATU

Perbandingan Objek

Dua variabel sama (==) hanya kalau menunjuk ke objek yang SAMA PERSIS:

javascript
let a = {};
let b = a; // referensi sama
console.log(a === b); // true

let c = {};
let d = {}; // dua objek BERBEDA (walau isinya sama)
console.log(c === d); // false

Menyalin Objek (Shallow Copy)

Kalau mau bikin salinan yang independen:

javascript
const user = { nama: "Budi", umur: 25 };

// Cara 1: Object.assign
const salinan1 = Object.assign({}, user);

// Cara 2: Spread operator (LEBIH MODERN)
const salinan2 = { ...user };

salinan2.nama = "Andi";
console.log(user.nama); // "Budi" — aman, tidak berubah!

⚠️ Jebakan: Nested Object (Shallow vs Deep Copy)

Object.assign dan spread hanya menyalin level pertama. Objek di dalam objek tetap berbagi referensi!

javascript
const user = {
  nama: "Budi",
  alamat: {
    kota: "Jakarta",
    kodePos: "12345"
  }
};

const salinan = { ...user };
salinan.alamat.kota = "Bandung";

console.log(user.alamat.kota); // "Bandung" — IKUT BERUBAH!

Deep Copy dengan structuredClone

Untuk menyalin objek secara mendalam (semua level):

javascript
const user = {
  nama: "Budi",
  alamat: {
    kota: "Jakarta",
    kodePos: "12345"
  }
};

const salinanDalam = structuredClone(user);
salinanDalam.alamat.kota = "Bandung";

console.log(user.alamat.kota); // "Jakarta" — AMAN!

structuredClone adalah fitur modern (tersedia di Node.js 17+ dan browser modern). Untuk kasus sederhana, spread {...obj} sudah cukup.

🎯Challenge
javascript
const original = {
  nama: "Laptop",
  spek: {
    ram: 8,
    storage: 256
  }
};

// Buat salinan DEEP dari original
// Ubah ram di salinan jadi 16
// Pastikan original.spek.ram tetap 8

3.3 Garbage Collection (Pengumpulan Sampah)

Konsep Dasar

JavaScript punya garbage collector — sistem otomatis yang menghapus data dari memori kalau sudah tidak dipakai.

Aturan utama: Objek yang masih bisa "dijangkau" (reachable) dari kode kita, tetap hidup di memori. Kalau tidak ada yang mereferensikan lagi, dia dihapus.

javascript
let user = { nama: "Budi" };

// Objek { nama: "Budi" } bisa dijangkau lewat variabel 'user'

user = null;

// Sekarang tidak ada yang mereferensikan objek tadi
// Garbage collector akan menghapusnya dari memori
💡Analogi

Bayangkan memori itu gudang. Garbage collector itu petugas kebersihan yang rutin cek: "Barang ini masih ada yang pakai? Kalau tidak, buang."

Kapan Objek Tetap Hidup?

javascript
let user = { nama: "Budi" };
let admin = user; // dua referensi ke objek yang sama

user = null; // satu referensi hilang

// Objek MASIH hidup karena 'admin' masih mereferensikan
console.log(admin.nama); // "Budi"

Kenapa Perlu Tahu Ini?

Sebagai pemula, kamu tidak perlu mengatur garbage collection secara manual. Tapi penting tahu:

  • Jangan simpan referensi ke objek besar yang sudah tidak dipakai
  • Set ke null kalau sudah selesai dengan objek besar
  • Memory leak terjadi kalau objek "terjebak" — masih direferensikan padahal sudah tidak dibutuhkan
🎯Challenge
javascript
let a = { data: "penting" };
let b = a;
let c = b;

a = null;
b = null;

// Pertanyaan: Apakah objek { data: "penting" } masih ada di memori?
// Kenapa?

3.4 Method Objek dan "this"

Objek Bisa Punya Fungsi!

Di dunia nyata, objek tidak cuma punya data — mereka juga bisa melakukan sesuatu. User bisa login, mobil bisa jalan, dll.

Fungsi yang ada di dalam objek disebut method:

javascript
const user = {
  nama: "Budi",
  umur: 25,

  // Ini method
  spiHalo() {
    console.log("Halo!");
  }
};

user.spiHalo(); // "Halo!"

Keyword "this"

Bagaimana method mengakses data objeknya sendiri? Pakai this:

javascript
const user = {
  nama: "Budi",
  umur: 25,

  perkenalan() {
    console.log(`Halo, nama saya ${this.nama}, umur ${this.umur} tahun`);
  }
};

user.perkenalan(); // "Halo, nama saya Budi, umur 25 tahun"

this = "objek yang memanggil method ini". Saat user.perkenalan() dipanggil, this merujuk ke user.

Kenapa Tidak Langsung Pakai Nama Variabel?

javascript
const user = {
  nama: "Budi",
  perkenalan() {
    // Ini BISA tapi BERBAHAYA:
    console.log(user.nama);
  }
};

const admin = user;
user = null; // Ups!

admin.perkenalan(); // ERROR! user sudah null

Kalau pakai this.nama, kode tetap aman meskipun variabel asli dihapus.

"this" Tidak Terikat (Unbound)

Di JavaScript, this ditentukan saat pemanggilan, bukan saat penulisan:

javascript
function spiHalo() {
  console.log(this.nama);
}

const user1 = { nama: "Budi", spiHalo };
const user2 = { nama: "Andi", spiHalo };

user1.spiHalo(); // "Budi" — this = user1
user2.spiHalo(); // "Andi" — this = user2

⚠️ Jebakan: Arrow Function Tidak Punya "this"

Arrow function tidak punya this sendiri. Dia "pinjam" dari fungsi luar:

javascript
const user = {
  nama: "Budi",

  // SALAH — arrow function tidak punya this sendiri
  spiHalo: () => {
    console.log(this.nama); // undefined!
  },

  // BENAR — pakai function biasa atau shorthand
  spiHalo2() {
    console.log(this.nama); // "Budi"
  }
};

Aturan simpel: Untuk method objek, SELALU pakai shorthand namaMethod() {} atau function. Jangan arrow function.

Method Chaining

Trik keren: method yang mengembalikan this bisa dipanggil berantai:

javascript
const kalkulator = {
  nilai: 0,

  tambah(n) {
    this.nilai += n;
    return this; // kunci chaining!
  },

  kali(n) {
    this.nilai *= n;
    return this;
  },

  tampilkan() {
    console.log(this.nilai);
    return this;
  }
};

kalkulator.tambah(5).kali(3).tampilkan(); // 15
🎯Challenge

Buat objek keranjang dengan:

  • Properti items (array kosong)
  • Method tambah(namaBarang) — push ke items, return this
  • Method hapus(namaBarang) — hapus dari items, return this
  • Method tampilkan() — console.log semua items

Gunakan chaining: keranjang.tambah("Apel").tambah("Jeruk").hapus("Apel").tampilkan()


3.5 Constructor dan Operator "new"

Masalah: Membuat Banyak Objek Serupa

Kalau mau bikin 10 user, masa harus tulis objek literal 10 kali?

javascript
// Capek kalau harus begini terus:
const user1 = { nama: "Budi", umur: 25 };
const user2 = { nama: "Andi", umur: 30 };
const user3 = { nama: "Cici", umur: 22 };
// ...

Solusi: Constructor Function

Constructor function = "cetakan" untuk membuat objek:

javascript
function User(nama, umur) {
  this.nama = nama;
  this.umur = umur;
  this.isAdmin = false;
}

const user1 = new User("Budi", 25);
const user2 = new User("Andi", 30);
const user3 = new User("Cici", 22);

console.log(user1); // { nama: "Budi", umur: 25, isAdmin: false }
console.log(user2); // { nama: "Andi", umur: 30, isAdmin: false }

Aturan Constructor:

  1. Nama diawali huruf kapital (konvensi, bukan wajib)
  2. Dipanggil dengan new

Apa yang Terjadi Saat new Dipanggil?

javascript
function User(nama) {
  // 1. JavaScript bikin objek kosong: this = {}
  // 2. Fungsi dijalankan, mengisi this
  this.nama = nama;
  this.isAdmin = false;
  // 3. this dikembalikan secara otomatis
}

// Jadi new User("Budi") menghasilkan:
// { nama: "Budi", isAdmin: false }

Method di Constructor

javascript
function User(nama, umur) {
  this.nama = nama;
  this.umur = umur;

  this.perkenalan = function() {
    console.log(`Halo, saya ${this.nama}`);
  };
}

const budi = new User("Budi", 25);
budi.perkenalan(); // "Halo, saya Budi"

⚠️ Jebakan: Lupa new

Kalau lupa pakai new, this tidak merujuk ke objek baru — hasilnya undefined (strict mode) atau bug aneh:

javascript
function User(nama) {
  this.nama = nama;
}

// BENAR:
const user1 = new User("Budi");
console.log(user1.nama); // "Budi"

// SALAH (lupa new):
const user2 = User("Budi"); // undefined!
// Di non-strict mode, malah "mencemari" objek global

Kapan Pakai Constructor vs Object Literal?

SituasiPakai
Objek unik, sekali pakaiObject literal {}
Banyak objek dengan struktur samaConstructor function
Nanti (Bab 8)Class (versi modern constructor)
🎯Challenge

Buat constructor Handphone(merk, harga, tahunRilis) yang:

  • Menyimpan ketiga parameter sebagai properti
  • Punya method deskripsi() yang return string: "Handphone [merk], harga Rp[harga], rilis tahun [tahunRilis]"
  • Buat 3 instance handphone berbeda dan panggil deskripsi() masing-masing

3.6 Optional Chaining (?.)

Masalah: Akses Properti yang Mungkin Tidak Ada

javascript
const user = {}; // user tanpa alamat

// Ini ERROR:
// console.log(user.alamat.kota);
// TypeError: Cannot read properties of undefined

// Cara lama (ribet):
console.log(user.alamat ? user.alamat.kota : undefined);

Solusi: Optional Chaining ?.

javascript
const user = {};

console.log(user?.alamat?.kota); // undefined (TANPA error!)

?. artinya: "Kalau bagian sebelum ?. ada (bukan null/undefined), lanjut. Kalau tidak ada, berhenti dan kembalikan undefined."

Contoh Praktis

javascript
const user1 = {
  nama: "Budi",
  alamat: {
    kota: "Jakarta",
    kodePos: "12345"
  }
};

const user2 = {
  nama: "Andi"
  // tidak punya alamat
};

console.log(user1?.alamat?.kota); // "Jakarta"
console.log(user2?.alamat?.kota); // undefined (aman!)

Varian Lain

javascript
const user = {
  nama: "Budi",
  admin: null
};

// ?.() — panggil method yang mungkin tidak ada
user.admin?.(); // tidak error, cuma undefined

// ?.[] — akses properti bracket yang mungkin tidak ada
const kunci = "nama";
console.log(user?.[kunci]); // "Budi"

⚠️ Jebakan: Jangan Overuse!

javascript
// SALAH — user HARUS ada (ini bug kalau null)
user?.nama;

// BENAR — alamat BOLEH tidak ada
user.alamat?.kota;

Pakai ?. hanya di tempat yang memang boleh kosong. Jangan pakai di mana-mana — nanti bug tersembunyi.

🎯Challenge
javascript
const toko = {
  nama: "Toko ABC",
  cabang: {
    jakarta: {
      alamat: "Jl. Sudirman No. 1",
      manager: { nama: "Budi" }
    }
  }
};

// Akses nama manager cabang "jakarta" — AMAN
// Akses nama manager cabang "bandung" — AMAN (undefined, bukan error)
// Akses telepon manager cabang "jakarta" — AMAN (undefined, bukan error)

3.7 Tipe Symbol

Apa Itu Symbol?

Symbol adalah tipe primitif yang menghasilkan identifier unik. Setiap Symbol yang dibuat dijamin berbeda, bahkan kalau deskripsinya sama.

javascript
const id1 = Symbol("id");
const id2 = Symbol("id");

console.log(id1 === id2); // false! Selalu unik

Kenapa Perlu Symbol?

Bayangkan kamu pakai objek dari library orang lain. Kamu mau tambah properti, tapi takut bentrok dengan properti yang sudah ada:

javascript
// Objek dari library lain
const user = { nama: "Budi", id: 123 };

// BAHAYA — kalau library juga pakai "id":
user.id = 456; // Menimpa id asli!

// AMAN — pakai Symbol:
const myId = Symbol("id");
user[myId] = 456; // Tidak bentrok!

console.log(user.id);     // 123 (asli, aman)
console.log(user[myId]);  // 456 (punya kita)

Symbol Tersembunyi dari for...in

javascript
const id = Symbol("id");
const user = {
  nama: "Budi",
  umur: 25,
  [id]: 123
};

for (let kunci in user) {
  console.log(kunci); // "nama", "umur" — Symbol tidak muncul!
}

// Tapi masih bisa diakses langsung:
console.log(user[id]); // 123

Kapan Pakai Symbol?

Jujur, sebagai pemula kamu jarang perlu bikin Symbol sendiri. Tapi penting tahu karena:

  • JavaScript internal pakai banyak Symbol (Symbol.iterator, Symbol.toPrimitive, dll)
  • Library besar pakai Symbol untuk "hidden properties"
  • Nanti di bab lanjutan (iterator, class) kamu akan ketemu Symbol lagi

Global Symbol

Kalau mau Symbol yang sama di berbagai tempat:

javascript
// Di file A:
const id = Symbol.for("userId");

// Di file B (Symbol yang SAMA):
const idLagi = Symbol.for("userId");

console.log(id === idLagi); // true!
🎯Challenge
javascript
// Buat Symbol bernama "rahasia"
// Tambahkan ke objek user sebagai properti dengan nilai "kode-xyz"
// Buktikan bahwa for...in TIDAK menampilkan properti Symbol
// Tapi kamu tetap bisa mengaksesnya langsung

3.8 Konversi Objek ke Primitif

Kapan Objek Dikonversi?

Saat objek dipakai di konteks yang butuh primitif:

javascript
const user = { nama: "Budi" };

// String context:
alert(user); // "[object Object]" — default jelek

// Number context:
const num = +user; // NaN

// Perbandingan:
console.log(user > 0); // false

Tiga "Hint" Konversi

JavaScript memberi "hint" ke objek tentang tipe apa yang diharapkan:

  1. "string" — saat butuh string (misal alert(obj))
  2. "number" — saat butuh angka (misal +obj, perbandingan)
  3. "default" — saat operator ambigu (misal obj + "")

Symbol.toPrimitive

Cara paling modern untuk mengontrol konversi:

javascript
const user = {
  nama: "Budi",
  uang: 1000,

  [Symbol.toPrimitive](hint) {
    if (hint === "string") {
      return `User: ${this.nama}`;
    }
    if (hint === "number") {
      return this.uang;
    }
    // default
    return this.uang;
  }
};

console.log(`${user}`);  // "User: Budi" (hint: string)
console.log(+user);      // 1000 (hint: number)
console.log(user + 500); // 1500 (hint: default)

Cara Lama: toString dan valueOf

javascript
const user = {
  nama: "Budi",
  uang: 1000,

  toString() {
    return `User: ${this.nama}`;
  },

  valueOf() {
    return this.uang;
  }
};

console.log(String(user)); // "User: Budi"
console.log(+user);        // 1000

Kapan Perlu Ini?

Sebagai pemula, kamu jarang perlu override konversi. Tapi penting tahu:

  • Kenapa alert(obj) menampilkan [object Object]
  • Bagaimana library seperti Moment.js bisa bikin +date menghasilkan timestamp
  • Nanti di class, kamu bisa bikin objek yang "pintar" saat dikonversi
🎯Challenge
javascript
// Buat objek "produk" dengan nama dan harga
// Implementasikan Symbol.toPrimitive sehingga:
// - String(produk) → "Produk: [nama]"
// - +produk → harga (number)
// - produk + 100 → harga + 100

Ringkasan Bab 3

KonsepPoin Kunci
ObjekKumpulan key-value, akses via dot/bracket
ReferensiObjek disalin by reference, bukan by value
Garbage CollectionOtomatis hapus objek yang unreachable
Method & thisFungsi di objek, this = pemanggil
ConstructorCetakan objek, pakai new + huruf kapital
Optional Chaining?. untuk akses aman properti nested
SymbolIdentifier unik, tersembunyi dari for...in
Konversi PrimitifSymbol.toPrimitive, toString, valueOf

Next: Bab 4 — Tipe Data (Array, Map, Set, dan lainnya)

Sudah paham materi ini?

Tandai sebagai selesai untuk melacak progress-mu.