类是什么

虽然ES6提供了class关键字用于创建对象,但其终究只是语法糖,底层并未实现。

// ES6创建类
class Hero {
  constructor() {
    this.name = "张无忌";
    this.sayMe = function () {
      console.log("this is 张无忌");
    };
  }
}

类的声明

  1. 类的声明方式

    class name [extends]{
        // class body
    }

    name表示当前类的名称。此方法不允许再次声明已经存在的类,否则会抛出一个类型错误。

  2. 类的表达方式

    const MyClass = class [className] [extends]{
        // class body
    }

    和函数表达式相同的一点是,类表达式可以是命名也可以是匿名的。如果是命名类表达式,这个名字只能在类体内部才能访问到。

构造函数

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

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

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

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

class Hero {
  constructor() {
    this.name = "张无忌";
    this.say = function () {
      console.log("Im am ", this.name);
    };
  }
}

let hero = new Hero();
hero.say(); //Im am  张无忌

getter和setter

在“类”的内部可以使用get和set关键字,对某个属性设置存值函数取值函数,拦截该属性的存取行为

class Hero {
  constructor() {
    this.v = 100;
  }
  get getV() {
    return this.v;
  }
  set setV(value) {
    this.v = value;
  }
}
var obj = new Hero();
console.log(obj.getV); // 100

静态方法

static name(){
    // code
}

在类的内部允许定义静态方法,静态方法不会被添加到当前类的实例中。通过类直接调用此方法。

class Hero {
  constructor() {
    this.name = "张无忌";
  }
  static sayMe() {
    console.log("this is 张无忌");
  }
}

Hero.sayMe(); // this is 张无忌

在一个静态方法中调用另外一个静态方法。

class Hero {
  constructor() {
    this.name = "张无忌";
    this.sayMe = () => {
      console.log("this is ", this.name);
      // 在constructor中调用静态方法是类名直接调用
      Hero.sayYou();
    };
  }
  // 不可枚举的方法
  toString() {
    console.log("name toString", this.name);
  }
  static sayYou() {
    console.log("this is sayYou");
  }
    static sayHe() {
    // 在静态方法中可以使用类名,也可以使用this
    // Hero.sayYou();
    this.sayYou();
  }
}

let hero = new Hero();
hero.sayMe();

Hero.sayHe();
  1. constructor中只能通过类名调用
  2. 在静态方法中可以通过类名调用也可以通过this调用。

类的继承

类在继承时使用关键字extends关键字即可。

class Child extends Parent {
  constructor() {
    super(); // super指向当前子类的父类的构造器
    this.age = 18;
  }
}

继承的类会继承类的方法,静态方法和构造函数。

class Parent {
  constructor() {
    this.name = "parent";
    this.sayMe = function () {
      console.log("this is sayMe");
    };
  }
  sayYou() {
    console.log("this is sayyou");
  }
  static staticMethod() {
    console.log("this is staticMethod");
  }
}

// 声明child类时,指定child类作为Parent类的子类
class Child extends Parent {
  constructor() {
    super(); // super指向当前子类的父类的构造器
    this.age = 18;
  }
}

let child = new Child();
console.log(child); // 
child.sayYou();
Child.staticMethod();

image-20201027170309833

继承实例

class myDate extends Date {
  constructor() {
    super();
  }
  getFormattedDate() {
    let months = [
      "Jan",
      "Feb",
      "Mar",
      "Apr",
      "May",
      "Jun",
      "Jul",
      "Aug",
      "Sep",
      "Oct",
      "Nov",
      "Dec",
    ];
    return `${this.getDate()}-${months[this.getMonth()]}-${this.getFullYear()}`;
  }
}

let date = new myDate();

console.log(date.getFormattedDate()); // 27-Oct-2020

通过继承一个Date对象,对其扩展自己的方法。

super关键字

  1. super关键字作为函数调用时,代表父类的构造函数。ES6要求子类的构造函数必须执行一次super函数

    super虽然代表了父类A的构造函数,但是返回的是子类B的实例。

  2. super当作对象时,在普通方法中,指向父类的原型对象。在静态方法中,指向父类。

    由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。

类的完整示例

// 定义一个类
class Parent {
  // 表示当前类的构造器(如果省略,JavaScript会自动生成)
  constructor(name) {
    this.name = name;
  }
  // 类的方法,不是原型方法
  toString() {
    console.log("this is parent toString");
    return "this is parent toString";
  }
  // 由当前类直接调用的方法
  static staticMethod() {
    console.log("this is parent static");
    return "this is parent static";
  }
  sayMe() {
    console.log("this is parent sayMe");
    return "this is parent sayMe";
  }
}
// 类具有原型
Parent.prototype.sayYou = function () {
  console.log("this is parent sayYou");
  return "this is parent sayYou";
};
//
class Child extends Parent {
  constructor(name, age) {
    super(name); // 指向父类构造器
    this.age = age;
    super.sayMe(); // 指向父类的实例对象
    super.sayYou(); // 指向父类的实例对象
  }
  toString() {
    console.log("this is child toString", super.toString());
  }
  static staticMethod() {
    console.log("this is child static", super.staticMethod());
  }
}

let child = new Child("XiaoKang", 18);
console.log(child);
// 将子类和父类的相同方法同时调用
child.toString();
Child.staticMethod();