# Classes

## BaselineWidely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

## 定義類別

### 類別宣告

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

#### Hoisting

js
``````var p = new Polygon(); // ReferenceError

class Polygon {}
``````

### 類別敘述

js
``````// 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;
}
};
``````

## 類別主體與方法定義

### 原型方法

js
``````class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea();
}
// Method
calcArea() {
return this.height * this.width;
}
}

const square = new Polygon(10, 10);

console.log(square.area); //100
``````

### 靜態方法(Static methods)

js
``````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)); // 7.0710678118654755
``````

### Instance properties

Instance properties 必須在 class 內定義:

js
``````class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
``````

### 宣告欄位

#### 宣告公共欄位

js
``````class Rectangle {
height = 0;
width;
constructor(height, width) {
this.height = height;
this.width = width;
}
}
``````

#### 宣告私有欄位

js
``````class Rectangle {
#height = 0;
#width;
constructor(height, width) {
this.#height = height;
this.#width = width;
}
}
``````

### 裝箱、原型方法及靜態方法

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

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

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

js
``````function Animal() {}

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

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

let obj = new Animal();
let speak = obj.speak;
speak(); // 全域物件

let eat = Animal.eat;
eat(); // 全域物件
``````

## 用 `extends` 建立子類別

js
``````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(); // Mitzie barks.
``````

js
``````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(); // Mitzie barks.
``````

js
``````var Animal = {
speak() {
console.log(this.name + " makes a noise.");
},
};

class Dog {
constructor(name) {
this.name = name;
}
}

// 如果你沒有用以下的方法，當你呼叫speak時會出現TypeError
Object.setPrototypeOf(Dog.prototype, Animal);

var d = new Dog("Mitzie");
d.speak(); // Mitzie makes a noise.
``````

## Species

js
``````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
``````

## 用 `super` 呼叫父類別

js
``````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.");
}
}

var l = new Lion("Fuzzy");
l.speak();
// Fuzzy makes a noise.
// Fuzzy roars.
``````

TBD

TBD

## 瀏覽器相容性

BCD tables only load in the browser