类是什么

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

1
2
3
4
5
6
7
8
9
// ES6创建类
class Hero {
constructor() {
this.name = "张无忌";
this.sayMe = function () {
console.log("this is 张无忌");
};
}
}

类的声明

  1. 类的声明方式

    1
    2
    3
    class name [extends]{
    // class body
    }

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

  2. 类的表达方式

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

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

构造函数

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
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关键字,对某个属性设置存值函数取值函数,拦截该属性的存取行为

1
2
3
4
5
6
7
8
9
10
11
12
13
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

静态方法

1
2
3
static name(){
// code
}

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

1
2
3
4
5
6
7
8
9
10
class Hero {
constructor() {
this.name = "张无忌";
}
static sayMe() {
console.log("this is 张无忌");
}
}

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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关键字即可。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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

继承实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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调用的。

类的完整示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 定义一个类
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();