类是属于构造函数的

类名首字母要大写

面向类的设计模式:

  • 实例化

  • 继承:继承意味着复制操作,JavaScript默认并不会复制对象的属性。相反,JavaScript会在两个对象之间创建一个关联,这样一个对象就可以通过委托访问另一个对象的属性和函数。

    • 原型继承
    • 差异继承
  • 多态:父类通用行为可以被子类用更特殊的行为重写。

可以使用类对数据结构进行分类,可以把任意数据结构看作范围更广的定义的一种特例。

ES6新增了 class 关键字,那是不是意味着 JavaScript 中实际上有类了呢?简单来说,不是。

类是一种设计模式,所以可以用一些方法近似实现类的功能。

构造函数

类实例是由一个特殊的类方法构造的,这个方法名通常和类名相同,被称为构造函数。这个方法的任务就是初始化实例需要的所有信息(状态)。

1class Person {
2  say() {
3    console.log("say");
4  }
5}
6
7const person = new Person();
8person.say(); // say

类的继承

类的继承其实就是复制,子类得到的只是父类的一份副本。

super:从子类的构造函数中国呢通过 super 可以直接调用父类的构造函数。

由于 JavaScript 中父类和子类的关系只存在于两者构造函数对应的 .prototype 对象中,因此它们的构造函数之间并不存在直接联系,从而无法简单地实现两者的相对引用(在 ES6 的类中可以通过 super 来解决这个问题)。

混入

混入实现继承

在继承或者实例化时,JavaScript并不会自动执行复制行为。简单来说,JavaScript中只有对象,并不存在可以被实例化的“类”。一个对象并不会被复制到其他对象,它们会被关联起来。

由于在其他语言中类表现出来的都是复制行为,因此 JavaScript开发者也想出了一个方法来模拟类的复制行为,这个方法就是混入。

对象只能复制引用

定义类

class 体内部的代码总是在严格模式下执行

类声明

1class Person {
2  name;
3
4  constructor(name) {
5    this.name = name;
6  }
7
8  introduceSelf() {
9    console.log(`Hi! I'm ${this.name}`);
10  }
11}

类表达式

类表达式是定义类的另一种方法。类表达式可以命名或不命名。命名类表达式的名称是该类体的局部名称。

1let Person = class {
2  name;
3  
4  constructor(name) {
5    this.name = name;
6  }
7
8  introduceSelf() {
9    console.log(`Hi! I'm ${this.name}`);
10  }
11}

函数声明类声明之间的一个重要区别在于,函数声明会提升,类声明不会。

属性

私有属性

私有数据属性必须在类的声明中声明,而且其名称需以 # 开头。

公有静态字段

公有实例字段

构造方法

在一个类中只能有一个名为“constructor”的特殊方法。一个类中出现多次构造函数 (constructor)方法将会抛出一个 SyntaxError) 错误。

在一个构造方法中可以使用super关键字来调用一个父类的构造方法。

如果没有显式指定构造方法,则会添加默认的 constructor 方法。

如果不指定一个构造函数 (constructor) 方法,则使用一个默认的构造函数 (constructor)。

构造函数使用 constructor 关键字来声明。就像在类声明外的构造函数一样,它会:

  • 创建一个新的对象
  • this 绑定到这个新的对象,你可以在构造函数代码中使用 this 来引用它
  • 执行构造函数中的代码
  • 返回这个新的对象

一个类只能拥有一个名为“constructor”的特殊方法。

省略构造函数

如果你不需要任何特殊的初始化内容,你可以省略构造函数,默认的构造函数会被自动生成

1class Animal {
2  sleep() {
3    console.log("zzzzzzz");
4  }
5}
6
7const spot = new Animal();
8
9spot.sleep(); // 'zzzzzzz'

方法

原型方法

静态方法

static 关键字用来定义一个类的一个静态方法。

不能在类的实例上调用静态方法,而应该通过类本身调用。

私有方法

# 开头,只能在类自己的方法中调用

继承

我们使用 extends 关键字来声明这个类继承自另一个类。

构造函数中需要做的第一件事是使用 super() 调用父类的构造函数,并传递父类构造函数期望的任何参数。

如果子类有任何自己的初始化内容需要完成,它也必须先使用 super() 来调用父类的构造函数,并传递父类构造函数期望的任何参数。