# Javascript Class 類
## 定義
類為特殊的函式,類也具有 類表達式 與 類陳述式 兩種形式。
### 類陳述式
```javascript
// 定義 類的基本方式
class Polygon {
constructor(height, weight){
this.height = height;
this.weight = weight;
}
}
```
### 類表達式
```javascript
// 不具名類
let Polygon = class {
constructor(height, weight){
this.height = height;
this.weight = weight;
}
}
console.log(Polygon.name) // Polygon
let Polygon2 = class Polygon2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
console.log(Polygon2.name) // Polygon2
```
#### 類 主體與方法定義
主體為`{}`內包含的部分,可在其中定義其成員(members)與方法(methods)或是建構子(constructor)
##### 建構子 Constructor
建構子作為定義類的初始化預設值使用,一個類只能有一個constructor,若定義多個constructor時則會SyntaxError,如果不需要定義預設值則,constructor也可以省略。
##### 方法 Methods
```javascript
class Polygon {
// constructor
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);
```

> ##### GETTER | SETTER
> getter method 是在 class 中沒有帶參數就可以回傳值的方法,可以透過 get 設定;setter method 則是可以透過 `=` 來對物件賦值,可以使用 set 來設定
> ```javascript
> class Person {
> constructor({ firstName, lastName, country = 'Taiwan' } = {}) {
> this.firstName = firstName;
> this.lastName = lastName;
> this.country = country;
> }
>
> // getter method
> get name() {
> return this.firstName + ' ' + this.lastName;
> }
>
> // setter method
> set name(input) {
> [this.firstName, this.lastName] = input.split(' ');
> }
>}
>
> let aaron = new Person({ firstName: 'Aaron', lastName: 'Chen' });
> console.log(aaron.name); // 使用 getter method,Aaron Chen
> aaron.name = 'Peter Chen'; // 使用 setter method
> console.log(aaron.name); // Peter Chen
> ```
##### 靜態方法 static
靜態方法不需要實體化它所屬類別的實例就可以被呼叫,它也無法被已實體化的類別物件呼叫。靜態方法經常被用來建立給應用程式使用的工具函數。
```javascript
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static displayName = 'Point';
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);
p1.displayName;
// undefined
p1.distance;
// undefined
console.log(Point.displayName);
// "Point"
console.log(Point.distance(p1, p2));
// 7.0710678118654755
// 呼叫靜態方法的第二種方式
class Bird {
constructor({ color = 'red' } = {}) {
this.color = color;
}
static changeColor(bird, color) {
// this 原本指稱的是所建立的 Bird 這個 Class
bird.color = color;
}
}
let redBird = new Bird();
console.log(redBird.color); // red
// redBird.changeColor('blue') // redBird.changeColor is not a function
Bird.changeColor(redBird, 'blue');
console.log(redBird.color); // blue
```
### 使用 extends 來進行繼承創建子類
```javascript
class Person {
constructor({ name, age = 18 } = {}) {
this.name = name;
this.age = age;
}
dance() {
console.log('old dance');
}
}
class Student extends Person {
constructor({ name, age, interestLevel = 5 } = {}) {
// 因為這是 extends from Person,所以我們必須要在為 instance 賦值前,
// 在 Student constructor 裡面呼叫 super function,
// 呼叫 super function 的意思就是呼叫 Person 的 constructor function。
super({ name, age });
this.name = name;
this.age = age;
this.interestLevel = interestLevel;
this.grades = new Map();
}
// 如果 traditional = true,則使用 Person 的 dance();否則...
// 也就是說,subclass 是可以覆蓋 superclass 的 method
dance(traditional) {
if (traditional) {
super.dance(); // 呼叫 Person 的 dance method
} else {
const dances = ['lyrical', 'tap', 'ballet', 'jaz'];
console.log(
`${this.name} is doing the ${dances[Math.floor(Math.random() * dances.length)]}!`,
);
}
}
}
let stevenJ = new Student({ name: 'Steven', age: 22 });
stevenJ.grades.set('Math', 10);
stevenJ.dance();
console.log(stevenJ);
console.log(`stevenJ's interestLevel is: ${stevenJ.interestLevel}`);
```
###### tags: `Javascript`