Memahami Javascript sebagai Prototype-based Language

Prototype adalah konsep fundamental yang harus diketahui oleh Programmer yang ingin belajar Javascript secara mendalam

Javascript adalah bahasa yang menantang untuk dipelajari. Karena konsep yang ditawarkan berbeda dari bahasa pemrograman interpreter kebanyakan seperti PHP, Python, atau Ruby. Javascript adalah bahasa yang asynchronous, non-blocking, dan prototype-based. Di artikel ini, kita akan membedah Javascript dari style yang digunakan yaitu Prototype-based Language.

Objects, Objects, Objects Everywhere!

You make prototype objects, and then … make new instances. Objects are mutable in JavaScript, so we can augment the new instances, giving them new fields and methods. These can then act as prototypes for even newer objects. We don’t need classes to make lots of similar objects… Objects inherit from objects. What could be more object oriented than that?
- Douglas Crockford

Pada Javascript, object memegang peranan yang sangat penting. Bahkan function diperlakukan sebagai First Class Objects yang artinya sebuah function dapat disimpan dalam data structure, dijadikan argumen atau dijadikan return value dari function lain. Mari kita lihat contoh kode di bawah ini :

Jika kita jalankan di terminal maka hasilnya

Untuk lebih jelasnya, mari kita replikasi contoh kode di atas ke dalam chrome console

Poinnya adalah, sebuah function dianggap “belum aktif” jika ditulis tanpa (). Belum aktif disini artinya function tidak akan langsung dieksekusi oleh program dan dapat diperlakukan seperti object biasa. Di Javascript, kita akan sering menemukan object dengan property yang memiliki value berupa function. Property ini disebut dengan method.

Selain itu, karena Javascript tidak mengenal konsep class, maka inheritance atau pewarisan dari satu object ke object lain menggunakan sebuah property khusus yang dimiliki oleh semua object yaitu prototype.

Inheritance via Prototype Chain

Konsep inheritance via prototype chain biasanya membuat bingung programmer yang datang dari background bahasa pemrograman berbasis class. Karena memang di Javascript tidak dikenal konsep class. Sekedar informasi, pada ES6 memang dikenalkan sintaks class, namun sintaks itu hanyalah syntatic sugar dari prototype itu sendiri. Seperti yang telah dibahas sebelumnya, object mewarisi property object lainnya melalui prototype chain.

Next, kita akan membahas bagaimana implementasi inheritance via prototype chain pada regular object dan constructor function.

__proto__ Property dan Object.create

Sebelum kita masuk ke pembahasan __proto__ property pada object, saya perlu mengingatkan bahwa mengakses__proto__ secara langsung sangat tidak disarankan karena dampaknya yang signifikan pada performance. Contoh dibawah ini bertujuan untuk memudahkan penjelasan tentang inheritance melalui __proto__ object. Namun jangan mengimplementasikannya di production level.

Kita akan coba menjalankan kode tersebut di chrome console

Hanya dengan meng-assign object bird ke dalam property __proto__ yang dimiliki object eagle, secara otomatis object eagle mewarisi semua property dari object bird. Mudah bukan ? Kita coba dengan 1 contoh lagi :

Seperti yang kita lihat diatas, meng-assign object X ke dalam __proto__ object Y akan membuat object Y mewarisi seluruh property dari object X. Begitu pula dengan object Z yang mewarisi seluruh property dari object Y yang sebelumnya mewarisi property dari object X. Inilah cara kerja dari prototype chaining. Andaikan kita mengakses sebuah property dari object misalnyabird.food, maka Javascript akan mencari property food pada object bird. Jika tidak ditemukan, maka Javascript akan menelusuri prototype yang mengarah ke parent dari object tersebut sampai property food ditemukan. Begitu seterusnya sampai akhirnya Javascript mengembalikan value dari property food atauundefined jika property food benar-benar tidak ditemukan.

Tadi sempat kita bahas bahwa inheritance melalui __proto__ tidak disarankan. Javascript telah menyediakan alternatif yang dapat kita gunakan yaitu Object.create. Mari kita refactor contoh-contoh diatas dengan menggunakan Object.create. Note: Object.create adalah fitur yang baru ada sejak ES5 dan tidak bisa berjalan di browser lama seperti IE8.

Jika 2 scripts ini dijalankan maka hasilnya akan sama dengan contoh yang memakai __proto__. Dan yang perlu dicatat, perubahan state yang terjadi di parent menyebabkan state yang ada di child berubah, sementara perubahan state di child tidak berpengaruh pada parent. Berikut contohnya:

dan jika kita jalankan di terminal

Selanjutnya kita akan membahas inheritance pada constructor function.

Constructor Functions

Metode inheritance via constructor function ini adalah metode yang cukup populer alias sering digunakan oleh para programmer Javascript. Caranya adalah dengan membuat sebuah function yang menjadi constructor dari object. Object yang diturunkan dari constructor function disebut dengan instance. Untuk lebih jelasnya mari kita lihat implementasi constructor function di bawah ini :

Jika kita jalankan di terminal

Function memiliki sebuah property khusus yang bernama prototype. Apa bedanya dengan property__proto__ yang telah kita bahas tadi ? Nah disinilah poin yang (lagi-lagi) membuat bingung programmer dalam memahami Javascript. Perlu dicatat bahwa tidak seperti regular object yang hanya memiliki property __proto__, function memiliki 2 macam prototype property : __proto__ dan prototype. Property__proto__ pada function tidak sama dengan propertyprototypenya.

Lalu apakah property prototype yang terdapat pada function tersebut? Secara sederhana, semua function di Javascript memiliki property prototype. Fungsi utama dari property prototype ini adalah sebagai shared resource yang digunakan oleh semua instance dari sebuah constructor function, baik yang ada sekarang maupun yang akan dipanggil di masa depan. Semua object yang dibuat dengan menggunakan new akan mewarisi seluruh property yang ada di prototype ini. Bagaimana cara kerjanya akan kita bahas di bawah.

Lalu apa bedanya jika kita memakaiprototype? Bukankah sama saja hasilnya jika kita menuliskanBird.prototype.color = 'brown' dengan this.color = 'Brown’ pada constructor Bird ? Secara fungsional memang sama, namun penggunaan prototype memiliki kelebihan yaitu optimasi memory. Mari kita lihat penjelasan kode di bawah ini :

Note : untuk menandai bahwa function tersebut adalah constructor function, huruf pertama dari nama function tersebut diawali dengan huruf kapital.

Sekarang kita coba jalankan kode di atas

Sekilas nampak sama karena baik foo.c() dan bar.c() sama-sama mengembalikan nilai 3. Akan tetapi ketika kita menginspeksi instance foo dan bar dengan console.log terlihat perbedaan bahwa instance dari function Foo terdiri dari 3 object, sementara instance dari function Bar hanya terdiri dari 2 object saja. Berarti jika ada 100 instance dari masing-masing Foo dan Bar, maka Foo akan menghabiskan 300 slot memory sementara Bar hanya 200. Padahal secara fungsional, keduanya memiliki hasil yang sama. Inilah yang dimaksud dengan optimasi memory dengan menggunakan prototype.

Bagaimana itu bisa terjadi sebenarnya tidak lepas dari cara kerja dari keyword newyaitu :

  1. new akan membuat sebuah object baru, dan semua this yang ada di constructor akan di-bind ke object yang baru.
  2. Property prototype pada constructor akan di-set ke property __proto__ pada object yang baru dibuat tadi.

Poin 1 sudah dibuktikan dengan kode yang ada di atas, sekarang mari kita buktikan poin 2

Bingo! bisa kita lihat ternyata Bar.prototype sama dengan (new Bar()).__proto__ yang artinya property prototype yang ada pada constructor function akan di-assign ke dalam __proto__ instance yang dipanggil dengan new. Jika kita bedah object bar (yang dibuat dari new Bar()), terlihat bahwa function c() berada di property __proto__ object bar.

Kesimpulan

Sekarang kita sudah memahami bahwa ada 2 cara untuk melakukan inheritance di Javascript yaitu dengan Object.create dan constructor. Di pembahasan terakhir ini, mari kita bandingkan implementasi inheritance dengan menggunakan Object.create dan constructor.

Dengan constructor :

Dengan Object.create :

Dan jika dijalankan, 2 script di atas memberikan hasil yang sama :

Jadi menurut teman-teman, manakah yang lebih mudah dipahami, inheritance dengan Object.create atau constructor ? Tinggalkan komentar di bawah ya 😊


Terimakasih telah membaca artikel ini. Apabila anda menyukainya klik ❤️ dan share serta follow medium, facebook, atau twitter Koding Kala Weekend untuk mendapat info tentang artikel terbaru kami.