面向对象的继承
一,普通继承:
继承思想:通过改变父类的执行环境,调用父类的构造函数,并改变父类的this指向。
<script>
//创建一个父类对象:
function Father(){
//添加属性:
this.heritage = 8888888888888888;
this.skill = function(){
console.log('经营一家上市公司');
}
}
//创建一个子类对象:
function Son(){
//添加一个属性,指向父类的构造函数
this.inheritor = Father;
//在子类中调用父类构造函数:
this.inheritor();
//执行完父类构造函数后,inheritor属性对子类来说无用,可以删掉,
delete.this.inheritor;
}
//new一个继承人对象:
var s1 = new Son();
console.log(s1.heritage,s1.skill());
</script>
缺点:父类中可变的属性,子类在继承属性时,值为undefined;
<script>
//创建一个父类对象:
function Father(name){
//添加属性:
this.heritage = 8888888888888888,
this.name = name;
this.skill = function(){
console.log('经营一家上市公司');
}
}
//创建一个子类对象:
function Son(){
//添加一个属性,指向父类的构造函数
this.inheritor = Father;
//在子类中调用父类构造函数:
this.inheritor();
//执行完父类构造函数后,inheritor属性对子类来说无用,可以删掉,
//delete.this.inheritor;
}
//new一个继承人对象:
var s1 = new Son();
console.log(s1.name);//undefined
</script>
要解决上面出现的小bug,就需要借助call,apply,bind来继承。
二,构造函数继承(call,apply,bind继承):
继承原理:在子类中使用call和apply方法调用父类,并改变this指向,使其指向子类new出来的对象。
1.call继承:
用法:父类.call(this指向,继承属性)
<script> function Father(name,age,tel){ //实例属性: this.name = name, this.age = age, this.tel = tel; //实例方法: this.running = function(){ console.log('经营一家咖啡厅'); } } function Son(name,age,tel){ Father.call(this,name,age,tel);//调用父类构造函数,改变this指向为Son构造出的对象S1 } var s1 = new Son('jinzi','88','123XX'); var s2 = new Son('yinzi','89','124XX'); console.log(s1,s2); </script>
2.apply继承:
用法:父类.apply(this指向,[继承属性]/arguments)
<script> function Father(name,age,tel){ //实例属性: this.name = name, this.age = age, this.tel = tel; //实例方法: this.running = function(){ console.log('经营一家咖啡厅'); } } function Son(name,age,tel){ //Father.apply(this,[name,age,tel]);//调用父类构造函数,改变this指向为Son构造出的对象S1 Father.apply(this,arguments);//arguments是参数副本,在使用参数副本时要注意:所有传递参数的位置保持一致。 } var s1 = new Son('jinzi','88','123XX'); var s2 = new Son('yinzi','89','124XX'); console.log(s1,s2); </script>
3.call和apply的区别:
call的参数不固定;
apply的参数是一个数组或arguments(参数副本)
4.bind继承:
用法:父类.bind(this指向)(继承属性)
<script> function Father(name,age,tel){ //实例属性: this.name = name, this.age = age, this.tel = tel; //实例方法: this.running = function(){ console.log('经营一家咖啡厅'); } } function Son(name,age,tel){ Father.bind(this)(name,age,tel); } var s1 = new Son('jinzi','88','123XX'); var s2 = new Son('yinzi','89','124XX'); console.log(s1,s2); </script>
三、原型链继承:
<script> function Animal(name,age){ //实例属性: this.name = name; this.age = age; //实例方法: // this.running = function(){ // console.log('eating'); // } } //原型方法: Animal.prototype.running = function(){ console.log('sleeping'); } function Dog(name,age){ } //让子类的原型对象指向父类的实例: Dog.prototype = new Animal('niuniu',4); var niuniu = new Dog(); console.log(niuniu.running()); </script>
注意:在使用原型继承时,如果父类的属性值不固定,继承时,子类无法更改这些属性值。要解决这个问题需要构造函数继承和原型链继承结合起来使用。
四,混合继承——构造函数+原型链继承:
<script> function Animal(name,age){ //实例属性: this.name = name; this.age = age; //实例方法: // this.running = function(){ // console.log('eating'); // } } //原型方法: Animal.prototype.running = function(){ console.log('sleeping'); } function Dog(name,age){ //构造函数继承 Animal.call(this,name,age); } //让子类的原型对象指向父类的实例: //原型继承: Dog.prototype = new Animal(); var niuniu = new Dog('niuniu',4); var maomao = new Dog('maomao',8); console.log(niuniu.running()); console.log(maomao); </script>
五、es6继承:
<script>
//定义父类:
class Animal{
constructor(name,color){
//属性:
this.name = name,
this.color = color
}
//方法:
eat(){
console.log('吃鱼')
}
running(){
console.log('奔跑')
}
}
//定义子类,继承父类Animal;
class Dog extends Animal{
constructor(name,color){
super(name,color);//继承父类所有的属性和方法
}
}
var damao = new Dog('damao','grey');
var ermao = new Dog('ermao','black');
console.log(damao,ermao);
damao.eat();
ermao.running();
</script>

浙公网安备 33010602011771号