一、原型链继承
将父类的实例作为子类的原型
function Parent(){
this.name='lily';
this.info={
score:99,
color:"red"
}
}
Parent.prototype.getMessage = function(){
console.log(this.name,this.info)
}
function Child(){
}
Child.prototype = new Parent();
let child1 = new Child('lily',18,'女');
child1.info.score = 100
child1.getMessage();
let child2 = new Child();
child2.getMessage();
优点:
父类方法可以复用
缺点:
父类的所有引用属性(info)会被所有子类共享,更改一个子类的引用属性,其他子类也会受影响
子类型实例不能给父类型构造函数传参
二、构造函数继承
在子类构造函数中调用父类构造函数,可以在子类构造函数中使用call()和apply()方法
function Parent(name){
this.name=name;
this.info={
age:18,
score:88,
}
}
Parent.prototype.getMessage=function(){
console.log(`${this.name}在跑`);
}
function Child(name,sex){
Parent.call(this,name);
this.sex=sex;
}
let child1 = new Child('zhangsan',18);
child1.info.age=88;
// child1.getMessage()会报错 Uncaught TypeError: child1.getMessage is not a function
console.log(child1)
let child2 = new Child('李四',16);
console.log(child2)
优点:
可以在子类构造函数中向父类传参数
父类的引用属性不会被共享
缺点:
子类不能访问父类原型上定义的方法(即不能访问Parent.prototype上定义的方法),因此所有方法属性都写在构造函数中,每次创建实例都会初始化
三、组合继承
组合继承综合了原型链继承和盗用构造函数继承(构造函数继承),将两者的优点结合了起来,
基本的思路就是使用原型链继承原型上的属性和方法,而通过构造函数继承实例属性,这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性
function Parent(name){
this.name= name||'gy'
this.colors = ['red','pink','gold']
}
Parent.prototype.drink = function(){
console.log(`${this.name}在喝水`)
}
function Child(name,sex){
// 继承父类的属性
Parent.apply(this,[name]);
// 拥有自己的属性
this.sex=sex;
}
// 继承父类的方法
Child.prototype = new Parent();
Child.prototype.run = function(){
console.log(`${this.name}在跑`);
}
let child1 = new Child('lucy','女');
child1.colors.push("blue")//数组是父类原型上的引用数据类型
console.log(child1);
child1.drink();
let child2 = new Child('Blank','男');
console.log(child2);
child2.drink();
上面例子中,Parent构造函数定义了name,colors两个属性,接着又在他的原型上添加了个drink ()方法。Child构造函数内部调用了Parent构造函数,同时传入了name参数,同时Child.prototype也被赋值为Parent实例,然后又在他的原型上添加了个run ()方法。这样就可以创建 child1,child2两个实例,让这两个实例都有自己的属性,包括colors,同时还共享了父类的drink方法
优点
父类的方法可以复用
可以在Child构造函数中向Parent构造函数中传参
父类构造函数中的引用属性不会被共享
Class继承:子类通过extends来继承父类,通过super来调用父类的构造函数,super必须放在子类this之前.
可以调用父类的属性和方法
class Person{
constructor(name) {
this.name=name
}
run(){
console.log(`${this.name}在跑`)
}
}
class Student extends Person{
constructor(name,score) {
super(name)
this.score=score
}
study(){
console.log(`${this.name}考了${this.score}分`);
}
}
let student = new Student('小明',98);
console.log(student)
student.study()
student.run()