Objek pada Javascript

Javascript memiliki dua jenis tipe data utama, yaitu tipe data dasar dan objek. Tipe data dasar pada Javascript adalah angka (numbers), rentetan karakter (strings), boolean (true dan false), null, dan undefined. Nilai-nilai selain tipe data dasar secara otomatis dianggap sebagai objek. Objek dalam Javascript didefinisikan sebagai mutable properties collection, yang artinya adalah sekumpulan properti (ciri khas) yang dapat berubah nilainya. Karena nilai-nilai selain tipe data dasar merupakan objek, maka pada Javascript sebuah Array adalah objek. Fungsi adalah objek. Regular expression juga adalah objek. Segala tipe buatan pengembang tentunya juga adalah objek.

Objek Javascript terdiri dari banyak properti. Masing-masing properti ini digunakan untuk mendeskripsikan objek tersebut. Sebuah properti idealnya berhubungan langsung dan mendeskripsikan objek dengan jelas. Misalkan, objek Mahasiswa biasanya akan memiliki properti NoInduk dan Nama tetapi tidak memiliki properti JumlahBaju karena nomor induk dan nama berguna untuk mendeskripsikan mahasiswa, sementara jumlah baju tidak penting. Contoh lainnya adalah objek Mobil yang mungkin memiliki properti WarnaBadan dan NoPolisi tetapi tidak memiliki properti JumlahKaki.

Properti pada objek memiliki nama dan nilai dari properti tersebut. Nama dari properti menjelaskan nilai yang disimpan oleh properti tersebut. Pada contoh sebelumnya, WarnaBadan adalah nama dari properti. Nilai dari properti merupakan “isi” dari nama properti. Contoh dari nilai pada WarnaBadan adalah Merah atau #FF0000. Nama dari properti harus berupa string, dan boleh berisi string kosong. Nilai dari properti lebih bebas, yaitu dapat berupa nilai apapun kecuali undefined. Hal ini berarti kita dapat mengisikan properti dengan nilai bertipe number, boolean, string, null, dan objek.

Pembuatan Objek pada Javascript

Objek pada Javascript bersifat class-free. Hal ini berarti kita tidak wajib mendefinisikan kelas terlebih dahulu agar dapat menggunakan sebuah objek (melalui inisiasi / constructor). Jika pada bahasa pemrograman lain (misalnya :code:`C#`) untuk membuat objek baru kita **harus* terlebih dahulu membuat kelas dari objek tersebut dan kemudian menggunakannya seperti berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// deklarasi kelas
public class Mobil {
    public String WarnaBadan { get; set; }
    // properti lain
}

// penggunaan kelas
var mercedes = new Mobil();

// gunakan kelas...
mercedes.WarnaBadan = "Merah";

maka pada Javascript kita tidak perlu mendefinisikan kelas terlebih dahulu untuk membuat objek. Notasi pembuatan objek pada Javascript sangat sederhana: sepasang kurung kurawal yang membungkus properti. Notasi pembuatan objek ini dikenal dengan nama object literal. Object literal dapat digunakan kapanpun pada ekspresi Javascript yang valid:

1
2
3
4
5
6
var objek_kosong = {};

var mobil = {
    "warna-badan": "merah",
    "nomor-polisi": "BK1234AB"
};

Nama properti dari sebuah objek harus berupa string, dan boleh berisi string kosong (""). Jika merupakan nama Javascript yang legal, kita tidak memerleukan petik ganda pada nama properti. Petik ganda seperti pada contoh ("warna-badan") hanya diperlukan untuk nama Javascript ilegal atau kata kunci seperti “if” atau “var”. Misalnya, "nomor-polisi" memerlukan tanda petik, sementara nomor_polisi tidak. Contoh lain, variasi tidak memerlukan tanda petik, sementara "var" perlu.

Sebuah objek dapat menyimpan banyak properti, dan setiap properti dipisahkan dengan tanda koma (,). Jika ada banyak properti, nilai dari properti pada setiap objek boleh berbeda-beda:

1
2
3
4
5
6
var jadwal = {
    platform: 34,
    telah_berangkat: false,
    tujuan: "Medan",
    asal: "Jakarta"
};

Karena dapat diisikan dengan nilai apapun (termasuk objek), maka kita dapat membuat objek yang mengandung objek lain (nested object; objek bersarang) seperti berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var jadwal = {
    platform: 34,
    telah_berangkat: false,
    asal: {
        kode_kota: "MDN",
        nama_kota: "Medan",
        waktu: "2013-12-29 14:00"
    },
    tujuan: {
        kode_kota: "JKT",
        nama_kota: "Jakarta",
        waktu: "2013-12-29 17.30"
    }
};

Perhatikan dan tandai objek jadwal dan mobil yang baru saja kita buat, karena bagian selanjutnya dari bab ini akan terus menggunakan kedua objek ini.

Akses Nilai Properti

Akses nilai properti dapat dilakukan dengan dua cara, yaitu:

  1. Penggunaan kurung siku ([]) setelah nama objek. Kurung siku kemudian diisikan dengan nama properti, yang harus berupa string. Cara ini biasanya digunakan untuk nama properti yang adalah nama ilegal atau kata kunci Javascript.
  2. Penggunaan tanda titik (.) setelah nama objek diikuti dengan nama properti. Notasi ini merupakan notasi yang umum digunakan pada bahasa pemrograman lainnya. Sayangnya kita tidak dapat menggunakan notasi ini untuk nama ilegal atau kata kunci Javascript.

Contoh penggunaan kedua cara pemanggilan di atas adalah sebagai berikut:

1
2
mobil["warna-badan"] // Hasil: "merah"
jadwal.platform      // Hasil: 34

Ingat bahwa meskipun kedua cara di atas dapat digunakan, umumnya kita lebih banyak menemukan cara kedua pada kode Javascript. Buku ini secara umum juga akan menggunakan notasi kedua, karena lebih banyak digunakan dan tidak ambigu dengan akses array.

Sebagai bahasa dinamis, Javascript tidak akan melemparkan pesan kesalahan jika kita mengakses properti yang tidak ada dalam objek. Kita akan menerima nilai undefined jika mengakses properti yang tidak ada:

1
2
jadwal.nomor_kursi   // Hasil: undefined
mobil["jumlah-roda"] // Hasil: undefined

Jika akan menyimpan nilai dalam variabel dan ingin memberikan nilai standar jika properti tidak ditemukan, kita dapat menggunakan operator ||:

1
2
var jumlah_roda = mobil["jumlah-roda"] || 4;  // jumlah_roda === 4
var nomor_kursi = jadwal.nomor_kursi || "A1"; // nomor_kursi === "A1"

Lebih jauh lagi, kita akan menerima pesan kesalahan TypeError jika mencoba mengakses properti dari properti yang sudah tidak ada seperti berikut:

1
2
// TypeError: Cannot read property 'nama' of undefined
jadwal.maskapai.nama

Hal ini terjadi karena ketika pemanggilan jadwal.maskapai Javascript memberikan nilai undefined karena memang jadwal tidak memiliki properti maskapai. Ketika kita memanggil properti nama, maka pada dasarnya kita mencoba menjalankan undefined.nama, yang tentunya akan menghasilkan error. undefined sudah pasti tidak memiliki properti nama.

Untuk menanggulangi hal ini, kita dapat menggunakan operator &&:

1
2
3
jadwal.maskapai                         // Hasil: undefined
jadwal.maskapai.nama                    // Hasil: TypeError
jadwal.maskapai && jadwal.maskapai.nama // Hasil: undefined

Tentunya kita juga dapat mengkombinasikan kedua operator ini untuk memberikan nilai standar jika properti tidak ada:

1
2
// nama_maskapai === "Garuda"
var nama_maskapai = jadwal.maskapai && jadwal.maskapai.nama || "Garuda";

Walaupun kombinasi kedua operator di atas jarang ditemukan, tetapi biasanya kita setidaknya menggunakan operator || untuk memastikan aplikasi yang dikembangkan tidak langsung berhenti berjalan dan rusak hanya karena sebuah properti tidak ditemukan.

Mengubah Nilai Properti

Di awal bab, kita berkata bahwa objek adalah kumpulan properti yang nilainya dapat berubah. Cara mengubah nilai properti sama dengan bahasa pemrograman lain pada umumnya, yaitu dengan menggunakan operator =:

1
jadwal.platform = 30;

Sifat dinamis Javascript lagi-lagi dapat dilihat ketika kita mencoba mengubah nilai dari properti yang tidak ada pada objek:

1
2
mobil["jumlah-roda"] = 4;
mobil.bahan_bakar = "Bensin";

Tidak akan ada pesan kesalahan pada kode di atas, karena Javascript akan langsung menambahkan kedua properti yang kita ingin ubah tersebut. Objek mobil sekarang akan menjadi seperti berikut:

1
2
3
4
5
6
var mobil = {
    "warna-badan": "merah",
    "nomor-polisi": "BK1234AB",
    "jumlah-roda": 4,
    bahan_bakar: "Bensin"
};

Kemudahan untuk menambah (dan mengubah) nilai properti dari objek secara dinamis ini merupakan salah satu kelebihan utama dari Javascript. Pada bab-bab selanjutnya kita akan banyak menggunakan teknik ini, baik dalam pemrograman berorientasi objek maupun fungsional. Pastikan untuk mengerti bagian ini dengan baik agar dapat dengan mudah mempelajari bab-bab selanjutnya.

Menghapus Properti

Jika sudah tidak ingin menggunakan sebuah properti, kita dapat melakukan penghapusan terhadap properti tersebut dengan menggunakan operator delete. Contoh penggunaannya adalah sebagai berikut:

1
2
3
4
5
6
mobil.bahan_bakar  // Hasil: "Bensin"

// hapus properti bahan_bakar dari mobil
delete mobil.bahan_bakar

mobil.bahan_bakar  // Hasil: undefined

Untuk sekarang, kita belum melihat kegunaan penuh dari fitur penghapusan properti ini. Kita akan melihat kembali kegunaan dari penghapusan properti setelah mempelajari bagian selanjutnya, yaitu Prototype.

Prototype

Pada bab sebelumnya kita telah beberapa kali mengatakan bagaimana Javascript menggunakan pendekatan yang berbeda dalam dukungannya terhadap pemrograman berorientasi objek. Jika bahasa lain pada umumnya menggunakan class-based OOP, Javascript menggunakan prototype-based OOP. Kita akan melihat apa maksud dari prototype-based OOP secara sekilas pada bagian ini. Pembahasan secara mendalam akan dilakukan pada bab selanjutnya, karena pembahasan protoyped-based OOP tak dapat lepas dari penggunaan fungsi.

Note

Mulai dari bagian ini, Prototype-Based OOP akan disingkat menjadi PBO saja, sementara Class-Based OOP akan disingkat CBO. Hal ini dilakukan untuk menghemat ruang tulisan.

PBO lebih banyak berbicara tentang penggunaan kembali kode, yang mana pada CBO salah satu mekanisme utamanya adalah inheritance. Pada CBO, ketika ingin menggunakan fitur inheritance biasanya kita harus membuat kelas dan kemudian melakukan penurunan dari kelas tersebut seperti berikut (contoh dalam bahasa C#):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class Mobil {
    // ..
}

// Truk sebagai turunan dari Mobil
public class Truk: Mobil {
    // Truk memiliki semua property dan method dari Mobil.
}

// Penggunaan kelas Truk
var tronton = new Truck();

// Truk juga adalah mobil
Mobil tronton = new Truck();

Pada Javascript yang mengimplementasikan PBO kita tidak lagi perlu menuliskan kelas, dan langsung melakukan penurunan terhadap objek. Misalkan kita memiliki objek mobil yang sederhana seperti berikut:

1
2
3
4
var mobil = {
    nama: "Mobil",
    jumlahBan: 4
};

Kita dapat langsung menurunkan objek tersebut dengan menggunakan fungsi Object.create seperti berikut:

1
2
3
var truk = Object.create(mobil);
// truk.nama === "Mobil"
// truk.jumlahBan === 4

Note

Fungsi Object.create merupakan fungsi baru yang terkadang tidak didukung oleh browser lama. Jika ingin menggunakan fungsi ini, kita dapat membuat fungsi sederhana yang mengimplementasikan fitur serupa seperti berikut:

1
2
3
4
5
6
7
if (typeof Object.create !== 'function') {
    Object.create = function(o) {
        var F = function() {};
        F.prototype = o;
        return new F();
    };
}

Tidak usah takut jika tidak mengerti sama sekali apa yang kita lakukan di atas. Bab selanjutnya akan membahas dengan detil cara kerja dari fungsi ini, dan kenapa fungsi ini diperlukan.

Pada kasus ini, mobil dikatakan adalah prototype dari truk. Segala nilai atau properti yang dimiliki oleh mobil secara otomatis akan juga dimiliki oleh truk. Semua objek yang kita buat dalam Javascript juga secara otomatis merupakan turunan dari objek Object.prototype, yang merupakan objek bawaan dari Javascript. Hal ini berarti mobil, dan seluruh turunannya, adalah turunan dari Object.prototype.

Hubungan antara turunan dan orang tua dari objek hanya berlaku untuk pengambilan nilai. Dalam contoh di atas, perubahan nilai pada properti di truk tidak akan mengubah nilai dari properti mobil:

1
2
truk.nama = "Tronton"; // mobil.nama tetap "Mobil"
truk.jumlahBan = 10;   // mobil.jumlahBan tetap 4

Ketika objek turunan memanggil properti yang kosong, maka Javascript secara otomatis akan mencari nama properti tersebut pada prototype-nya, dan jika masih tidak ada, properti akan dicari pada prototype dari objek prototype objek. Hal ini akan terus berlangsung sampai pengecekan dilakukan terhadap Object.prototype. Jika Object.prototype tidak memiliki properti tersebut juga, maka undefined akan dikembalikan. Misalnya jika kita memanggil properti yang memang kita tahu tidak ada pada truk:

1
truk.berat_maks // undefined

Maka proses pemanggilan yang terjadi sampai kita mendapatkan nilai undefined adalah sebagai berikut:

  1. Cek truk.berat_maks.
    1. Karena nilai tidak ada, cek orang tua dari truk.
    2. Orang tua dari truk adalah mobil.
  2. Cek mobil.berat_maks.
    1. Karena nilai tidak ada, cek orang tua dari mobil.
    2. Orang tua dari mobil adalah Object.prototype.
  3. Cek Object.prototype.berat_maks.
    1. Karena nilai tidak ada, kembalikan undefined.

Proses penelusuran properti ke atas sampai pada Object.prototype ini dikenal dengan nama delegasi (delegation). Kita dapat mencoba fitur delegasi ini misalnya dengan membuang properti dalam truk, dan kemudian mengaksesnya melalui kembali. Nilai yang diberikan akan menjadi nilai properti tersebut milik mobil:

1
2
delete truk.nama;
truk.nama         // Hasil: "Mobil"

Pengecekan nilai prototype ini juga bersifat dinamis. Hal ini berarti ketika kita menambahkan properti baru dalam prototype, seluruh objek turunan prototype tersebut akan dapat mengakses properti barunya. Contoh:

1
2
mobil.berat_maks = 3.0
truk.berat_maks        // Hasil: 3.0

Sejauh ini fasilitas penggunaan kembali kode pada PBO yang kita lihat masih belum terlalu berbeda dengan pada CBO, kecuali di bagian yang sifatnya dinamis. Kita akan melihat kekuatan yang sebenarnya dari PBO pada bab selanjutnya, setelah selesai membahas fungsi.

Penelusuran Nilai Properti

Dengan menggunakan perulangan for in kita dapat melakukan penelusuran terhadap satu per satu properti objek. Penelusuran akan dilakukan terhadap seluruh nilai milik objek: properti, method (fungsi milik objek), maupun properti hasil pewarisan (prototype). Langsung saja, lihat contoh berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var manusia = {
    kepala: 1,
    mata: 2,
    telinga: 2,
    tangan: 2,
    kaki: 2,
    jariTangan: 10,
    jariKaki: 10,
};

var namaProperti;
for (namaProperti in manusia) {
    console.log(namaProperti + ": " + manusia[namaProperti]);
}

// Keluaran kode di atas:
// kepala: 1
// mata: 2
// telinga: 2
// tangan: 2
// kaki: 2
// jariTangan: 10
// jariKaki: 10

Fitur ini seringkali berguna ketika kita ingin menggabungkan beberapa objek yang ada secara dinamis. Kegunaan lain lagi misalnya untuk memastikan sebuah properti ada di dalam objek. Kekurangan dari penelusuran seperti ini adalah jika kita menelusuri objek turunan, for in akan melakukan penelusuran terhadap properti-properti milik objek induk juga. Misalnya pada kode di bawah:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
var baju = {
    jenis: "Gaun",
    kain: "Sutra"
};

var kemeja = Object.create(baju);
kemeja.jenis = "Kemeja";
kemeja.kerah = true;

var nama;
for (nama in kemeja) {
    console.log(nama + ": " + kemeja[nama]);
}

// Keluaran kode di atas:
// jenis: Kemeja
// kerah: true
// kain: Sutra

Dalam kode di atas, dapat dilihat bagaimana jenis dan kain tetap ditelusuri oleh for in. Jika tidak ingin menelusuri nilai turunan, kita dapat menggunakan fungsi hasOwnProperty:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var nama;
for (nama in kemeja) {
    if (kemeja.hasOwnProperty(nama)) {
        console.log(nama + ": " + kemeja[nama]);
    }
}

// Keluaran kode di atas:
// jenis: Kemeja
// kerah: true

Dengan melakukan validasi menggunakan hasOwnProperty terlebih dahulu, kita dapat menghapus properti yang bukan asli milik objek. Perhatikan juga bagaimana jenis tetap ditelusuri. Hal ini terjadi karena jenis sudah kita isikan dengan nilai baru, sehingga jenis dianggap milik kemeja.

Terakhir, jika ingin tidak menelusuri method (detil tentang method dapat dibaca pada bab selanjutnya), kita dapat menggunakan ekspresi typeof untuk mengecek apakah sebuah properti fungsi atau bukan:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var objek = {
    prop1: "testing",
    meth1: function () { // sebuah method
        return "method";
    }
}

var nama;
for (nama in objek) {
    console.log(nama + ": " + objek[nama]);
}

// For di atas (yang tidak memiliki if) mencetak:
// prop1: testing
//  meth1: function () { // sebuah method
//      return "method";
//  }

for (nama in objek) {
    if (typeof objek[nama] !== "function") {
        console.log(nama + ": " + objek[nama]);
    }
}

// For kedua (yang memiliki if) mencetak:
// prop1: testing

Catatan lain yang juga perlu diingat adalah bahwa penelusuran properti dengan for in seperti ini tidak memperhatikan urutan penulisan properti pada objek. Meskipun terdapat beberapa cara untuk menghindari hal ini, kita lebih disarankan untuk tidak bergantung kepada urutan properti jika ingin melakukan penelusuran.

Penanganan Nilai Global

Pada bab sebelumnya kita telah membahas bahwa salah satu kesalahan desain yang paling fatal dari Javascript adalah penggunaan nilai global secara standar. Di bagian ini kita akan mencoba sedikit memperbaiki hal ini, dengan menggunakan objek.

Penanganan kita lakukan dengan membuat sebuah objek global yang menampung seluruh kode kita. Objek global ini merupakan objek yang pertama kali kita buat sebelum aplikasi dijalankan. Objek harus dibuat sebelum kode lain berjalan. Berikut adalah implementasi paling sederhana dari objek global kita:

1
var MYAPP = MYAPP || {};

Kode yang sangat sederhana. Kita hanya mendeklarasikan sekaligsu memanggil objek global kita, MYAPP, jika MYAPP telah dideklarasikan sebelumnya. Jika belum dideklarasikan, kita akan membuat sebuah objek kosong. Selanjutnya kita dapat mengisikan MYAPP dengan kode yang kita inginkan:

1
2
3
4
5
6
MYAPP.mobil = {
    nama: "Mobil",
    jumlahBan: 4
};

MYAPP.truk = Object.create(MYAPP.mobil);

Dengan menggunakan cara penulisan kode seperti di atas, kita akan mengurangi variabel yang ada pada skala global menjadi hanya satu variabel saja, yaitu MYAPP. Selain mengurangi sifat global dari aplikasi kita, dengan membuat objek global seperti ini kita juga secara otomatis mempermudah interaksi dengan library lain seperti jQuery atau Yui. Keuntungan lainnya adalah kemudahan pembacaan kode, karena kita akan dengan mudah mengetahui mana objek buatan kita dan mana objek buatan library lain. Hal ini juga lah yang menjadi alasan kenapa library javascript umumnya memiliki simbol khusus untuk pemanggilannya, misalnya $ pada jQuery atau YUI() pada YUI.

Pada bab berikutnya dan bab selanjutnya kita juga akan menambahkan fungsionalitas pada fungsi global ini, sehingga kita bisa memiliki fitur-fitur tambahan yang kerap ada pada bahasa OOP modern seperti namespace.

Penutup

Fitur pemrograman berorientasi objek pada Javascript masih belum kita bahas sepenuhnya pada bagian ini. Misalnya, kita sama sekali belum berbicara mengenai method, atau sebuah fungsi yang dapat dipanggil dari sebuah objek. Fitur ini akan kita bahas pada bab berikutnya, bersamaan dengan pembahasan fungsi Javascript secara umum. Kita akan melihat bagaimana fungsi berkaitan erat dengan objek pada Javascript, serta detil dari penggunaan fungsi dan objek secara bersamaan pada bab berikutnya.

Objek pada bab ini dibahas tidak terlalu mendalam karena memang pembahasan objek dalam Javascript sangat sulit dilakukan tanpa berbicara fungsi. Jadi tidak usah takut, kita akan melihat banyak lagi pembahasan mengenai objek pada bab berikutnya, dan kemudian kita akan membahas bagaimana menggunakan objek dan fungsi secara efektif pada bab-bab selanjutnya.

comments powered by Disqus
Kembali ke bertzzie.com