# 类

## 定义类

### 类声明

```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)) { }```

## 规范

Specification
ECMAScript (ECMA-262)
Class definitions
Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
Class definitions
Standard Initial definition.
ECMAScript 2016 (ECMA-262)
Class definitions
Standard
ECMAScript 2017 (ECMA-262)
Class definitions
Standard
ECMAScript (ECMA-262)
Class definitions
Living Standard

## 浏览器兼容

Update compatibility data on GitHub
Desktop Mobile Server Chrome Edge Firefox Internet Explorer Opera Safari Android webview Chrome for Android Firefox for Android Opera for Android Chrome Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. No support 42 — 49Disabled Disabled From version 42 until version 49 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). To change preferences in Chrome, visit chrome://flags. Edge Full support 13 Firefox Full support 45 IE No support No Opera Full support 36 Full support 36 No support 29 — 36Notes Notes Strict mode is required. No support 29 — 36Disabled Disabled From version 29 until version 36 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). Safari Full support 9 WebView Android Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. Chrome Android Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. No support 42 — 49Disabled Disabled From version 42 until version 49 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). To change preferences in Chrome, visit chrome://flags. Firefox Android Full support 45 Opera Android Full support 36 Full support 36 No support 29 — 36Notes Notes Strict mode is required. No support 29 — 36Disabled Disabled From version 29 until version 36 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). Safari iOS Full support 9 Samsung Internet Android Full support 5.0 Full support 5.0 No support 4.0 — 5.0Notes Notes Strict mode is required. nodejs Full support 6.0.0 Full support 6.0.0 Full support 4.0.0Disabled Disabled From version 4.0.0: this feature is behind the `--use_strict` runtime flag. Full support 5.0.0Disabled Disabled From version 5.0.0: this feature is behind the `--harmony` runtime flag. Chrome Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. No support 42 — 49Disabled Disabled From version 42 until version 49 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). To change preferences in Chrome, visit chrome://flags. Edge Full support 13 Firefox Full support 45 IE No support No Opera Full support 36 Full support 36 No support 29 — 36Notes Notes Strict mode is required. No support 29 — 36Disabled Disabled From version 29 until version 36 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). Safari Full support 9 WebView Android Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. Chrome Android Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. No support 42 — 49Disabled Disabled From version 42 until version 49 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). To change preferences in Chrome, visit chrome://flags. Firefox Android Full support 45 Opera Android Full support 36 Full support 36 No support 29 — 36Notes Notes Strict mode is required. No support 29 — 36Disabled Disabled From version 29 until version 36 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). Safari iOS Full support 9 Samsung Internet Android Full support 5.0 Full support 5.0 No support 4.0 — 5.0Notes Notes Strict mode is required. nodejs Full support 6.0.0 Full support 6.0.0 Full support 4.0.0Disabled Disabled From version 4.0.0: this feature is behind the `--use_strict` runtime flag. Full support 5.0.0Disabled Disabled From version 5.0.0: this feature is behind the `--harmony` runtime flag. Chrome Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. No support 42 — 49Disabled Disabled From version 42 until version 49 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). To change preferences in Chrome, visit chrome://flags. Edge Full support 13 Firefox Full support 45 IE No support No Opera Full support 36 Full support 36 No support 29 — 36Notes Notes Strict mode is required. No support 29 — 36Disabled Disabled From version 29 until version 36 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). Safari Full support 9 WebView Android Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. Chrome Android Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. No support 42 — 49Disabled Disabled From version 42 until version 49 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). To change preferences in Chrome, visit chrome://flags. Firefox Android Full support 45 Opera Android Full support 36 Full support 36 No support 29 — 36Notes Notes Strict mode is required. No support 29 — 36Disabled Disabled From version 29 until version 36 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). Safari iOS Full support 9 Samsung Internet Android Full support 5.0 Full support 5.0 No support 4.0 — 5.0Notes Notes Strict mode is required. nodejs Full support 6.0.0 Full support 6.0.0 Full support 4.0.0Disabled Disabled From version 4.0.0: this feature is behind the `--use_strict` runtime flag. Full support 5.0.0Disabled Disabled From version 5.0.0: this feature is behind the `--harmony` runtime flag. Chrome Full support 74 Edge Full support 79 Firefox Full support 81Disabled Full support 81Disabled Disabled From version 81: this feature is behind the `javascript.options.experimental.private_fields` preference (needs to be set to `true`) and the `javascript.options.experimental.private_methods` preference (needs to be set to `true`). To change preferences in Firefox, visit about:config. IE No support No Opera Full support 62 Safari No support No WebView Android Full support 74 Chrome Android Full support 74 Firefox Android Full support 81Disabled Full support 81Disabled Disabled From version 81: this feature is behind the `javascript.options.experimental.private_fields` preference (needs to be set to `true`) and the `javascript.options.experimental.private_methods` preference (needs to be set to `true`). To change preferences in Firefox, visit about:config. Opera Android Full support 53 Safari iOS No support No Samsung Internet Android No support No nodejs Full support 12.0.0 Chrome Full support 72 Edge Full support 79 Firefox Full support 69 IE No support No Opera Full support 60 Safari Partial support 14Notes Partial support 14Notes Notes Doesn't support public static fields. See WebKit bug 194095. WebView Android Full support 72 Chrome Android Full support 72 Firefox Android No support No Opera Android Full support 51 Safari iOS Partial support 14Notes Partial support 14Notes Notes Doesn't support public static fields. See WebKit bug 194095. Samsung Internet Android No support No nodejs Full support 12.0.0 Chrome Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. No support 42 — 49Disabled Disabled From version 42 until version 49 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). To change preferences in Chrome, visit chrome://flags. Edge Full support 13 Firefox Full support 45 IE No support No Opera Full support 36 Full support 36 No support 29 — 36Notes Notes Strict mode is required. No support 29 — 36Disabled Disabled From version 29 until version 36 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). Safari Full support 9 WebView Android Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. Chrome Android Full support 49 Full support 49 No support 42 — 49Notes Notes Strict mode is required. No support 42 — 49Disabled Disabled From version 42 until version 49 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). To change preferences in Chrome, visit chrome://flags. Firefox Android Full support 45 Opera Android Full support 36 Full support 36 No support 29 — 36Notes Notes Strict mode is required. No support 29 — 36Disabled Disabled From version 29 until version 36 (exclusive): this feature is behind the `Experimental JavaScript` preference (needs to be set to `Enabled`). Safari iOS Full support 9 Samsung Internet Android Full support 5.0 Full support 5.0 No support 4.0 — 5.0Notes Notes Strict mode is required. nodejs Full support 6.0.0 Full support 6.0.0 Full support 4.0.0Disabled Disabled From version 4.0.0: this feature is behind the `--use_strict` runtime flag. Full support 5.0.0Disabled Disabled From version 5.0.0: this feature is behind the `--harmony` runtime flag. Chrome Full support 72 Edge Full support 79 Firefox Full support 75 IE No support No Opera Full support 60 Safari No support No WebView Android Full support 72 Chrome Android Full support 72 Firefox Android No support No Opera Android Full support 51 Safari iOS No support No Samsung Internet Android No support No nodejs Full support 12.0.0

### Legend

Full support
Full support
Partial support
Partial support
No support
No support
See implementation notes.
See implementation notes.
User must explicitly enable this feature.
User must explicitly enable this feature.