ES6之类的继承
先看之前的写法:
function Animal(type, name){
this.type=type;
this.name=name;
}
Animal.prototype.print=function(){
console.log(`【种类】:${this.type}`);
console.log(`【名字】:${this.name}`);
}
function Dog(name){
//重新指向this,将父类的属性放到子类中
Animal.call(this, "犬类", name);
}
Object.setPrototypeOf(Dog.prototype,Animal.prototype)
const dog=new Dog();
dog.print();
console.log(dog)
A继承B的意思是A在B的范围内,可以说A是B的子类,也可以说B派生A。上面的例子是通过call方法调用重新指定this,将父类参数形成的对象放到子类中,同时,还需要绑定子类的隐式原型到父类中,完成闭环。 现在的写法:
class Animal {
constructor(type, name) {
this.type = type;
this.name = name;
}
print() {
console.log(`【种类】:${this.type}`);
console.log(`【名字】:${this.name}`);
}
}
class Dog extends Animal {
constructor(name) {
super("犬类", name);
}
}
const dog = new Dog("旺财");
dog.print();
console.log(dog);
现在我们可以直接使用 extends 表示继承关系,同时当子类中出现了 constructor 时,必须使用 super() 调用父类的构造函数,并且可以往里面传入参数。如果不写构造器的话,会自动加入一个构造器,并且使用与父类相同的构造器,相同的参数类型。
如果父类和子类有相同的原型方法,会在原型链上查找。首先会找到子类里的方法。
print()
{
//当作对象里使用,super代表父类原型
super.print();
console.log(`【爱好】:${this.loves}`);
}
如果是作为对象使用,super 代表父类的原型,super.print() 会调用父类的原型方法。类似于把父类的属性直接搬到这里。
if(new.target === Animal)
{
throw new Error("不能实例化抽象类");
}
当我们不想让一个抽象类可以创建对象时,可以加一个 new.target 的判断。因为如果这个类是抽象的,就不应该被实例化,这样会违反逻辑。
this 的指向不会在定义中更改,只会根据调用的对象决定。