Classes

Kelas di JavaScript diperkenalkan pada ECMAScript 6 seperti pemanis dari prototype-based JavaScript yang sudah ada. Syntax dari kelas tidak menggunakan model object-oriented inheritance yang baru. JavaScript kelas menyediakan syntax yang lebih sederhana dan rapi untuk membuat object-object dan mengatasi / dealing dengan turunan / inheritance.

Definisi kelas

Kelas seperti "fungsi istimewa", dan seperti kamu bisa mendeklarasikan ekspresi fungsi (function expressions) dan deklarasi fungsi (function declarations), syntax kelas sendiri mempunyai dua komponen: ekspresi kelas (class expressions) dan deklarasi kelas (class declarations).

Deklarasi Kelas

Salah satu cara untuk mendefinisikan kelas adalah dengan menggunakan class declaration / deklarasi kelas. Untuk mendeklarasikan kelas, kamu bisa menggunakan kata kunci class sebagai contoh class "Polygon" di bawah ini.

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

Hoisting

Perbedaan penting antara deklarasi fungsi (function declarations) dan deklarasi kelas (class declarations) adalah deklarasi fungsi  hoisted dan  deklarasi class tidak. Pertama-tama kamu harus mendeklarasikan kelas dan mengaksesnya, jika tidak maka kode seperti berikut akan menampilkan ReferenceError:

var p = new Polygon(); // ReferenceError

class Polygon {}

Ekspresi Kelas

Ekspresi kelas (class expression) adalah cara lain untuk mendefinisikan sebuah class. Class expression bisa bernama ataupun tidak. Nama yang diberikan berbentuk lokal berada di body class.

// unnamed
var Polygon = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};

// named
var Polygon = class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};

Catatan: Ekspresi kelas (Class expressions) juga mempunyai masalah yang sama terkait hoisting seperti pada Deklarasi kelas (Class declarations).

Tubuh Kelas (class body) and definisi metode

Tubuh atau body sebuah kelas berada didalam kurung {}. Disitu kamu dapat mendefinisikan isi kelas seperti method atau konstruktor.

Strict mode

Body atau bagian badan dari kelas deklarasi dan kelas ekspresi di eksekusi pada strict mode.

Konstruktor

konstruktor adalah metode (method) khusus untuk membuat dan inisialisasi sebuah objek yang dibuat dengan  class. Hanya ada satu metode khusus dengan nama "konstruktor" di kelas. Sebuah SyntaxError akan tampil jika kelas berisi lebih dari satu method constructor.

Sebuah konstruktor dapat digunakan keyword super untuk memanggil kostruktor dari kelas parent nya.

Prototipe method

Lihat juga definisi method

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  
  get area() {
    return this.calcArea();
  }

  calcArea() {
    return this.height * this.width;
  }
}

const square = new Polygon(10, 10);

console.log(square.area);

Metode Statis

Kata kunci statis mendefinisikan metode statis untuk suatu kelas. Metode statis dipanggil tanpa membuat instance kelasnya dan tidak bisa dipanggil ketika kelas tersebut dipakai. Metode statis sering digunakan untuk membuat fungsi utilitas untuk suatu aplikasi.

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  static distance(a, b) {
    const dx = a.x - b.x;
    const dy = a.y - b.y;

    return Math.sqrt(dx*dx + dy*dy);
  }
}

const p1 = new Point(5, 5);
const p2 = new Point(10, 10);

console.log(Point.distance(p1, p2));

Boxing dengan prototipe dan metode statis

Ketika metode statis atau prototipe dipanggil tanpa objek yang bernilai "this" (atau "this" sebagai boolean, string, angka, tidak terdefinisi atau null), maka nilai "this" akan ditentukan dalam fungsi yang digunakan. Autoboxing tidak akan berjalan. Hal tersebut juga berlaku ketika kita menulis kode dalam mode non-strict.laku akan sama bahkan jika kita menulis kode dalam mode tidak ketat.

class Animal { 
  speak() {
    return this;
  }
  static eat() {
    return this;
  }
}

let obj = new Animal();
let speak = obj.speak;
speak(); // undefined

let eat = Animal.eat;
eat(); // undefined

Jika kita menulis kode diatas menggunakan fungsi tradisional berdasarkan kelas, maka autoboxing akan berjalan sesuai dengan nilai "this" pada fungsi yang dipanggil.

function Animal() { }

Animal.prototype.speak = function(){
  return this;
}

Animal.eat = function() {
  return this;
}

let obj = new Animal();
let speak = obj.speak;
speak(); // global object

let eat = Animal.eat;
eat(); // global object

Sub kelas dengan extends

extends digunakan pada deklarasi kelas atau kelas expresi untuk membuat suatu kelas sebagai turunan dari kelas lain.

class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Dog extends Animal {
  speak() {
    console.log(this.name + ' barks.');
  }
}

var d = new Dog('Mitzie');
d.speak();

Jika terdapat constructor pada sub kelas saat ini, maka pertama dibutuhkan untuk memanggil super() sebelum menggunakan "this".

Seseorang juga dapat mengextend "kelas" berbasis fungsi tradisional:
function Animal (name) {
  this.name = name;  
}

Animal.prototype.speak = function () {
  console.log(this.name + ' makes a noise.');
}

class Dog extends Animal {
  speak() {
    console.log(this.name + ' barks.');
  }
}

var d = new Dog('Mitzie');
d.speak();

Perhatikan bahwa kelas tidak dapat di extend pada objek reguler atau biasa (non-constructible) . Jika ingin mewarisi regurel object,  maka dapat menggunakan Object.setPrototypeOf():

var Animal = {
  speak() {
    console.log(this.name + ' makes a noise.');
  }
};

class Dog {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(this.name + ' barks.');
  }
}

Object.setPrototypeOf(Dog.prototype, Animal);

var d = new Dog('Mitzie');
d.speak();

Species

Kamu dapat mengembalikan objek Array  di kelas array yang diturunkan MyArray. Pola spesies memungkinkan Kamu overide konstruktor default.

Contohnya, ketika menggunakan method seperti map() yang mana mengembalikan konstruktor default, kamu butuh method yang dapat mengembalikan objek parent Array, bukan dari objek MyArray. Simbol Symbol.species memungkinkan untuk melakukan:

class MyArray extends Array {
  // Overwrite species to the parent Array constructor
  static get [Symbol.species]() { return Array; }
}

var a = new MyArray(1,2,3);
var mapped = a.map(x => x * x);

console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array);   // true

Memanggil Kelas Super dengan keyword super

Keyword super digunakan untuk memanggil fungsi pada objek parent nya.

class Cat { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Lion extends Cat {
  speak() {
    super.speak();
    console.log(this.name + ' roars.');
  }
}

Mix-ins

Subkelas Abstrak or mix-ins adalah template untuk kelas. Kelas berbasis  ECMAScript hanya dapat memiliki satu superclass (Kelas super), jadi inheritence berganda dari kelas tool sebagai contohnya, itu tidak memungkinkan. Fungsionalitas harus disediakan oleh superclass.

Sebuah fungsi dengan superclass sebagai inputanya dan sukelas as input and a subclass extend superclass sebagai output dapat mengimplemtasikan pada  ECMAScript sebagai berikut:

var calculatorMixin = Base => class extends Base {
  calc() { }
};

var randomizerMixin = Base => class extends Base {
  randomize() { }
};

A class that uses these mix-ins can then be written like this:

class Foo { }
class Bar extends calculatorMixin(randomizerMixin(Foo)) { }

Spesifikasi

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Class definitions' in that specification.
Standard Initial definition.
ECMAScript Latest Draft (ECMA-262)
The definition of 'Class definitions' in that specification.
Draft  

Kompatibilitas Browser

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

Feature Chrome Firefox (Gecko) Edge Internet Explorer Opera Safari
Basic support 42.0[1]
49.0
45 (45) 13 No support No support 9.0
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
Basic support No support 45.0 (45) ? ? 9 42.0[1]
49.0

[1] Requires strict mode. Non-strict mode support is behind the flag "Enable Experimental JavaScript", disabled by default.

Lihat Juga