# 类是什么
虽然 ES6 提供了 class
关键字用于创建对象,但其终究只是语法糖,底层并未实现。
// ES6 创建类 | |
class Hero { | |
constructor() { | |
this.name = "张无忌"; | |
this.sayMe = function () { | |
console.log("this is 张无忌"); | |
}; | |
} | |
} |
# 类的声明
类的声明方式
class name [extends]{
// class body
}
name
表示当前类的名称。此方法不允许再次声明已经存在的类,否则会抛出一个类型错误。类的表达方式
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(); |
- 在
constructor
中只能通过类名调用 - 在静态方法中可以通过类名调用也可以通过
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(); |
# 继承实例
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 关键字
super
关键字作为函数调用时,代表父类的构造函数。ES6 要求子类的构造函数必须执行一次super
函数super
虽然代表了父类 A 的构造函数,但是返回的是子类 B 的实例。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(); |