在解释这个问题之前,我们先来看看传统的构造函数的问题
1.传统的构造函数
function Animal(type, name, age){
this.type = type;
this.name = name;
this.age = age;
}
Animal.prototype.print = function(){
console.log(`种类:${this.type}`);
console.log(`名字:${this.name}`);
console.log(`年龄:${this.age}`);
}
const dog = new Animal("狗", "旺财", 3);
dog.print();
for (const prop in dog) {
console.log(prop);
}
class Animal {
constructor(type, name, age) {
this.type = type;
this.name = name;
this.age = age;
}
print() {
console.log(`种类:${this.type}`);
console.log(`名字:${this.name}`);
console.log(`年龄:${this.age}`);
}
}
const dog = new Animal("狗", "旺财", 3);
dog.print();
for (const prop in dog) {
console.log(prop);
}
const printName = "print";
class Animal{
constructor(type, name, age, sex){
this.type = type;
this.name = name;
this.age = age;
this.sex = sex;
}
[printName](){
console.log(`[种类]:${this.type}`);
console.log(`[名字]:${this.name}`);
console.log(`[年龄]:${this.age}`);
console.log(`[性别]:${this.sex}`);
}
}
const a = new Animal('狗', '旺财', 3, '男');
a[printName]();
const printName = "print";
class Animal {
constructor(type, name, age, sex) {
this.type = type;
this.name = name;
this.age = age;
this.sex = sex;
}
//创建一个age属性,并给它加上getter,读取该属性时,会运行该函数
get age() {
return this._age + "岁";
}
//创建一个age属性,并给它加上setter,给该属性赋值时,会运行该函数
set age(age) {
this._age = age;
}
[printName]() {
console.log(`【种类】:${this.type}`);
console.log(`【名字】:${this.name}`);
console.log(`【年龄】:${this.age}`);
console.log(`【性别】:${this.sex}`);
}
}
var dog = new Animal("狗", "旺财", 3, "公");
//如果get和set使用类的age就会无限调用方法,所以必须返回一个跟age名不一样的变量名
class Chess {
constructor(name) {
this.name = name;
}
static width = 50;
static height = 50;
}
var a = new Chess();
console.log(Chess.width)
console.log(Chess.height)
console.log(a.width);
console.log(a.height);
const A = class {
a = 1;
b = 2;
}
const a = new A();
console.log(a)
如果B继承自A,则A派生B,B是A的子类,A是B的父类,B自动拥有A中的所有实例成员
extends:继承,用于类的定义
super:
1.如果直接当做函数调用,表示父类的构造函数
2.如果当做对象调用,则表示父类的原型
如果子类定义了constructor,则必须在constructor的第一行手动调用父类的构造函数,如果子类不写constructor,则会有默认的构造器,参数和父类一致,并自动调用父类构造器
这是一个抽象类
class Animal {
constructor(type, name, age, sex) {
if (new.target === Animal) {
throw new TypeError("你不能直接创建Animal的对象,应该通过子类创建")
}
this.type = type;
this.name = name;
this.age = age;
this.sex = sex;
}
print() {
console.log(`【种类】:${this.type}`);
console.log(`【名字】:${this.name}`);
console.log(`【年龄】:${this.age}`);
console.log(`【性别】:${this.sex}`);
}
say() {
throw new Error("动物怎么叫的?");
}
}
class Dog extends Animal {
constructor(name, age, sex) {
super("犬类", name, age, sex);
// 子类特有的属性
this.loves = "吃骨头";
}
print() {
//调用父类的print
super.print();
//自己特有的代码
console.log(`【爱好】:${this.loves}`);
}
//同名方法,会覆盖父类
say() {
console.log("汪汪!");
}
}
const a = new Dog("旺财", 3, "公")
a.print();
a.say();