本质上,类只是一种特殊的函数。

console.log(typeof 某类); //"function"
  • 1.

声明类 class

方式 1 – 类声明

class Car {
  constructor(model, year) {
    this.model = model;
    this.year = year;
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

方式 2 – 类表达式

匿名式

const Car = class {
  constructor(model, year) {
    this.model = model;
    this.year = year;
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

命名式 —— 类名称在表达式定义的内部有效,在外部无法使用

const NamedCar = class Car {
  constructor(model, year) {
    this.model = model;
    this.year = year;
  }
  getName() {
    return Car.name;
  }
}
const ford = new NamedCar();
console.log(ford.getName()); // Car
console.log(ford.name); // 引用错误: name未定义
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

构造函数 constructor

每个类只能存在一个,在构造器中可以通过super()方法来调用其父类的构造器。

类的属性(原型方法)

支持表达式命名,以下三种效果相同:

class CarOne {
  driveCar() {}
}
class CarTwo {
  ['drive' + 'Car']() {}
}
const methodName = 'driveCar';
class CarThree {
  [methodName]() {}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

类的修饰符

  • get 获取类的属性值
  • set 修改类的属性值
class Obj {
    c="我是原生的a,只是需要在this.c暂时存储",
    
    get a(){
     return this.c   
    },
    
    set a(val){
        this.c=val
    }
}
 
const obj = new Obj()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

使用类 new

class Car {
  constructor(model, year) {
    this.model = model;
    this.year = year;
  }
}
const fiesta = new Car('Fiesta', '2010');
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

类的继承 extends

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(this.name + ' generic noise');
  }
}
class Cat extends Animal {
  speak() {
    console.log(this.name + ' says Meow.');
  }
}
class Lion extends Cat {
  speak() {
    super.speak();
    console.log(this.name + ' Roars....');
  }
}
var l = new Lion('Lenny');
l.speak();
//"Lenny says Meow."
//"Lenny Roar...."
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 子类内通过 super 调用父类

在子类的构造器中,必须先调用super()方法才能正确地获取到this关键字

class Base {}
class Derive extends Base {
  constructor(name) {
    this.name = name; //'this' 不允许在 super()之前
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

子类中,如果定义了构造器,则必须在其中调用super()方法,否则会报错

class Base {}
class Derive extends Base {
  constructor() { //在构造器中没有调用super()方法
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 父类默认构造器
constructor(){}
  • 1.
  • 子类默认构造器
constructor(...args){
  super(...args);
}
  • 1.
  • 2.
  • 3.

多重继承

JavaScript本身不支持多重继承,在ES6中实现mixin的一种比较流行的实现方式是编写输入为父类输出为子类的函数,例如:

class Person {}
const BackgroundCheck = Tools => class extends Tools {
  check() {}
};
const Onboard = Tools => class extends Tools {
  printBadge() {}
};
class Employee extends BackgroundCheck(Onboard(Person)) {
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

Employee类依次顺序继承了BackgroundCheck类、Onboard类和Person类。

类和普通函数的区别

  • 类必须先声明,再使用
var ford = new Car(); //引用错误
class Car {}
  • 1.
  • 2.
  • 普通函数可用先使用,再声明
normalFunction();   //先使用
function normalFunction() {}  //后声明
  • 1.
  • 2.

【面试题】手写 class