# 类

## 定义类

### 类声明

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

#### 提升

``````let p = new Rectangle(); // ReferenceError

class Rectangle {}
``````

### 类表达式

``````// 未命名/匿名类
let Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name);
// output: "Rectangle"

// 命名类
let Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name);
// 输出: "Rectangle2"``````

## 类体和方法定义

### 构造函数

constructor方法是一个特殊的方法，这种方法用于创建和初始化一个由`class`创建的对象。一个类只能拥有一个名为 “constructor”的特殊方法。如果类包含多个`constructor`的方法，则将抛出 一个`SyntaxError`

### 原型方法

``````class Rectangle {
// 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 Rectangle(10, 10);

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

### 静态方法

`static` 关键字用来定义一个类的一个静态方法。调用静态方法不需要实例化该类，但不能通过一个类实例调用静态方法。静态方法通常用于为一个应用程序创建工具函数。

``````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.hypot(dx, 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
``````

### 用原型和静态方法绑定 this

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

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

### 实例属性

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

``````Rectangle.staticWidth = 20;
Rectangle.prototype.prototypeWidth = 25;```
```

### 字段声明

#### 公有字段声明

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

#### 私有字段声明

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

## 使用 `extends` 扩展子类

`extends` 关键字在 类声明 或 类表达式 中用于创建一个类作为另一个类的一个子类。

``````class Animal {
constructor(name) {
this.name = name;
}

speak() {
console.log(`\${this.name} makes a noise.`);
}
}

class Dog extends Animal {
constructor(name) {
super(name); // 调用超类构造函数并传入name参数
}

speak() {
console.log(`\${this.name} barks.`);
}
}

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

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

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

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

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

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

Object.setPrototypeOf(Dog.prototype, Animal);// 如果不这样做，在调用speak时会返回TypeError

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

## Species

``````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` 调用超类

`super` 关键字用于调用对象的父对象上的函数。

``````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 / 混入

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

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

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

## 浏览器兼容

BCD tables only load in the browser