6、原型继承和构造函数继承

原型继承

就是让类的prototype属性指向某个对象,这样该类的实例就能用它指向的那个对象的所有属性和方法。和C#的类继承差不多,子类可以用父类成员,只是js继承方法不一样,原型继承也是js中的一种继承方式
prototype就是原型,所有对象和类都有原型。如果是 function这种形式的类它的构造方法和类是它自己。

创建三个类

function Person(){
    this.typeName="人类";
}

function Chinese(){
    this.country="中国";
}

function SiChuanRen(){
    this.province="四川人";
}

让Chinese的原型继承Person,SiChuanRen的原型继承Chinese,并实例化SiChuanRen这个类

Chinese.prototype=new Person();
SiChuanRen.prototype=new Chinese();

var sichuan=new SiChuanRen();
console.log(sichuan);

输出结果可以看到:SiChuanRen的对象的一级原型对象竟然不是Chinese,那是因为,先设置了Chinese的原型,那么此时Chinese的原型就是Person了,然后SiChuanRen去继承Chinese,发现Chinese已经有了原型,所以就去继承Chinese的原型了。
image

所以要先让SiChuanRen去继承Chinese

SiChuanRen.prototype=new Chinese();
Chinese.prototype=new Person();

var sichuan=new SiChuanRen();
console.log(sichuan);

这样SiChuanRen的一级继承原型就是Chinese
image

原型继承的优点和缺点

优点

1、实例的原型是父类的实例。如:
image
2、实例可以继承的属性有:实例自己的构造函数属性,父类的构造函数属性,新实例不会继承父类的属性

缺点

1、新实例无法向父类构造函数传参 ,因为整个实例的原型就是父类的实例,父类都实例化了,也就是都调过父类的构造函数了。如:
image

2、继承单一,因为原型只有一个,原型已经继承了一个了就无法再继承其它类了。

3、所有的子类新实例都会共享父类实例的属性。父类实例的属性指的就是子类的原型链属性,因为所有子类的原型都是同一个父类,所以定义在子类的原型对象里的属性所有实例都是共享的("类名.prototype.属性名"),一个实例修改了原型属性的值,另一个实例相对应的原型属性的值也会被修改。

构造函数继承

为了解决原型继承的缺点,就可以使用构造函数继承

声明父类

 function Person(name){
     this.username=name;
 }

声明子类,让其继承父类

通过call()方法继承父类构造函数,本质上js没有继承这个概率,原型继承和构造函数继承都是模拟继承

 function Chinese(){
     Person.call(this,"中国人");
 }

实例化子类,输出父类的属性

var chinese=new Chinese();
 console.log(chinese.username);

也可以多级继承

 function Person(name){
     this.username=name;
 }

 function People(){
     this.age=18;
 }

 function Chinese(){
     Person.call(this,"中国人");
     People.call(this);
 }

 var chinese=new Chinese();
 console.log(chinese.username);
 console.log(chinese.age);

如果People也有一个属性叫username的话,那么实例输出的username就是people类的username属性,因为继承两个类,相同属性会被覆盖掉。

posted @ 2022-03-10 19:30  青仙  阅读(158)  评论(0编辑  收藏  举报