Belajar Membuat Object Di JavaScript


Apakah JavaScript mendukung OOP? Iya dan tidak! JavaScript tidak memiliki class seperti di Java dan C# sehingga pemograman OOP di JavaScript lebih condong ke arah prototype-based programming. Saya tidak akan berharap banyak membuat puluhan UML class diagram yang mewakili domain inventory, pembelian, penjualan, dan laba rugi, lalu meng-implementasi-kannya pada JavaScript. OOP pada JavaScript tidak untuk keperluan seperti itu sehingga banyak yang menyebutkan bahwa JavaScript tidak mendukung OOP. Bagi JavaScript, sebuah object adalah kumpulan nilai layaknya sebuah array (jangan lupa bahwa function di JavaScript adalah sebuah nilai).

Berikut ini adalah contoh definisi object di JavaScript:

var produkA = {
    nama: 'Produk A',
    harga: 120000,
    jumlah: 10,
    tersediaUntuk: function(dibutuhkan) {
        return this.jumlah >= dibutuhkan;
    }
}

var produkB = {
    nama: 'Produk B',
    harga: 85000,
    jumlah: 5,
    tersediaUntuk: function(dibutuhkan) {
        return this.jumlah >= dibutuhkan;
    }
}

console.log(produkA.tersediaUntuk(10));
console.log(produkA.tersediaUntuk(15));
console.log(produkB.tersediaUntuk(3));
console.log(produkB.tersediaUntuk(10));

Pada kode program di atas, saya memakai console.log() untuk mencetak output ke console milik browser Firefox atau Chrome. Untuk membuka console di Firefox, saya perlu memilih menu Developer, Web Console. Karena tidak ada konsep class, saya terpaksa menduplikasikan function tersediaUntuk() pada produkA dan produkB. Selain itu, tanpa class, produkA dan produkB boleh memiliki property yang berbeda walaupun mereka sama-sama mewakili produk.

JavaScript juga mendukung getter dan setter seperti pada Java untuk masing-masing property yang ada. Tapi cara mendefinisikannya agak merepotkan karena saya harus menggunakan Object.defineProperty() seperti pada contoh berikut ini:

var produkA = {
    nama: 'Produk A',
    harga: 120000,
    _jumlah: 10,
    tersediaUntuk: function(dibutuhkan) {
        return this.jumlah >= dibutuhkan;
    }
}
Object.defineProperty(produkA, 'jumlah', {
    get: function() {
        return this._jumlah;
    },
    set: function(nilai) {
        this._jumlah = (nilai < 0)? 0: nilai;
    }
});
produkA.jumlah = -10;
console.log(produkA.jumlah);  // output: 0

Tanpa class, saya harus mengulangi kode program di atas setiap kali saya ingin membuat object produkB, produkC, produkD, dan seterusnya. Ini adalah sesuatu yang melelahkan dan membuat kode program menjadi panjang. Untuk mengatasi masalah tersebut, developer JavaScript biasanya memakai constructor function. Sebagai contoh, kode program berikut ini adalah versi kode program yang memakai constructor function:

function Produk(nama, harga, jumlah) {
    this.nama = nama;
    this.harga = harga;
    Object.defineProperty(this, 'jumlah', {
        get: function() {
            return this._jumlah;
        },
        set: function(nilai) {
            this._jumlah = (nilai < 0)? 0: nilai;
        }
    });
    this.jumlah = jumlah;
    this.tersediaUntuk = function(dibutuhkan) {
        return this.jumlah >= dibutuhkan;
    }
}
var produkA = new Produk('Produk A', 120000, 10);
var produkB = new Produk('Produk B', 85000, 5);

console.log(produkA.nama); // output: Produk A
console.log(produkA.tersediaUntuk(5)); // output: true
produkA.jumlah = -10;
console.log(produkA.jumlah); // output: 0
console.log(produkB.nama); // output: Produk B
console.log(produkB.tersediaUntuk(10)); // output: false

Cara di atas lebih singkat karena saya seolah-olah memiliki class sehingga tidak ada duplikasi setiap kali membuat object baru. Bagi saya yang berasal dari Java, kode program di atas terlihat aneh, kenapa operator new dipadukan dengan sebuah Function? Di JavaScript, new harus selalu dipakai pada Function (sebagai pengganti class)! Operator new akan menciptakan sebuah object baru dan mengasosiasikan object baru tersebut dengan this di dalam function. Setelah function selesai dikerjakan, nilai dari this (object baru) akan dikembalikan.

Untuk mendapatkan informasi Function yang membuat object (di JavaScript, function seperti ini disebut constructor), saya dapat menggunakan kode program seperti:

console.log(produkA.constructor == Produk); // output: true
console.log(produkA instanceof Produk); // output: true
console.log(produkB.constructor == Produk); // output: true
console.log(produkB instanceof Produk); // output: true

Walaupun semuanya terlihat baik-baik saja sampai disini, ada satu permasalahan mendasar yang berhubungan dengan function. Pada JavaScript, sebuah nama function pada dasarnya adalah pointer ke function sehingga function dapat dianggap sebagai nilai (sama seperti pada property). Dengan menggunakan new di atas, setiap kali saya membuat object dengan Produk(), saya sebenarnya membuat nilai tersediaUntuk yang baru dan berbeda tetapi mengerjakan hal yang sama. Hal ini bisa dibuktikan dengan:

console.log(produkA.tersediaUntuk == produkB.tersediaUntuk); // output: false

Saya dapat mengatasi hal tersebut dengan menggunakan prototype (ini adalah fitur bawaan dari JavaScript dan tidak ada hubungannya dengan Prototype Framework!). Setiap kali sebuah function dibuat, JavaScript engine akan membuat property bernama prototype. Nilai prototype yang sama akan di-share ke seluruh object yang dibuat dengan function tersebut. Pada saat sebuah function dipanggil, JavaScript engine akan memeriksa apakah sebuah object memiliki function dengan nama yang akan dipanggil. Bila tidak ditemukan, JavaScript engine akan memeriksa apakah prototype untuk object tersebut mendefinisikan function yang akan dipanggil. Bila ada, maka function di prototype akan dikerjakan.

Sebagai contoh, berikut ini adalah versi yang memakai prototype:

function Produk(nama, harga, jumlah) {
    this.nama = nama;
    this.harga = harga;
    this.jumlah = jumlah;
}
Object.defineProperty(Produk.prototype, 'jumlah', {
    get: function () {
        return this._jumlah;
    },
    set: function (nilai) {
        this._jumlah = (nilai < 0) ? 0 : nilai;
    }
});
Produk.prototype.tersediaUntuk = function (dibutuhkan) {
    return this.jumlah >= dibutuhkan;
}
var produkA = new Produk('Produk A', 120000, 10);
var produkB = new Produk('Produk B', 85000, 5);
console.log(produkA.tersediaUntuk == produkB.tersediaUntuk); // output: true

Untuk melihat apa saja yang ada di prototype, saya dapat menggunakan Object.keys() seperti pada contoh kode program berikut ini:

var prototypeProdukA = Object.getPrototypeOf(produkA);
var prototypeProdukB = Object.getPrototypeOf(produkB);
console.log(prototypeProdukA == prototypeProdukB); // output: true
console.log(Object.keys(prototypeProdukA)); // output: ["tersediaUntuk"]
console.log(Object.keys(prototypeProdukB)); // output: ["tersediaUntuk"]

Sekarang, saya sudah mengetahui bagaimana pola yang umum dipakai untuk mendeklarasikan dan membuat object. Sebagai latihan, saya akan mencoba menambahkan beberapa class yang berbeda, misalnya Faktur dan ItemFaktur, seperti pada contoh berikut ini:

/** class Produk **/
function Produk(nama, harga, jumlah) {
    this.nama = nama;
    this.harga = harga;
    this.jumlah = jumlah;
};
Produk.prototype.tersediaUntuk = function (dibutuhkan) {
    return this.jumlah >= dibutuhkan;
};

/** class ItemFaktur **/
function ItemFaktur(produk, jumlah, harga) {
    this.produk = produk;
    this.jumlah = jumlah;
    this.harga = harga;
};
ItemFaktur.prototype.total = function () {
    return this.jumlah * this.harga;
};


/** class Faktur **/
function Faktur(nomor, tanggal, diskon) {
    this.nomor = nomor;
    this.tanggal = tanggal;
    this.items = [];
    this.diskon = diskon;
};
Faktur.prototype = {
    total: function () {        
        var totalItem = 0;
        this.items.forEach(function(item) {
            totalItem += item.total();
        });                    
        var totalDiskon = (this.diskon/100) * totalItem;
        return totalItem - totalDiskon;

    },
    tambah: function (produk, jumlah, harga) {
        this.items.push(new ItemFaktur(produk, jumlah, harga));
    }
};

/** Contoh Penggunaan **/
var produkA = new Produk('Produk A', 120000, 10);
var produkB = new Produk('Produk B', 85000, 5);
var faktur = new Faktur('FA-001', Date.now(), 10);
faktur.tambah(produkA, 5, 130000);
faktur.tambah(produkB, 10, 12000);
console.log(faktur); // output: {nomor: "FA-001", tanggal: 1401017015872, items: Array[2], diskon: 10}
console.log(faktur.total()); // output: 693000

Perihal Solid Snake
I'm nothing...

One Response to Belajar Membuat Object Di JavaScript

  1. Ping-balik: Belajar Memakai Inheritance Di JavaScript | The Solid Snake

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: