继上篇博客 https://www.cnblogs.com/qianqian-it/p/9526634.html 简单介绍了有关call和apply的联系和区别之后,接下来我们来共同学习一下面向对象的三个基本特征之一继承
1 首先来分析一下什么是继承
-
这里的继承和我们现实生活的中儿子继承父亲财产的这种关系虽然有相似的地方,但本质其实不一样;
-
举一个简单的例子理解继承的含义:
- 猴子--会法术的猴子--孙悟空;
- 会法术的猴子和猴子是我们这里所说的继承关系;
- 会法术的猴子是猴子的一种,即猴子是会法术的猴子的类型;
- 孙悟空是会法术的猴子的一个实例,即会法术的猴子是孙悟空的类;
- 孙悟空即使会法术的猴子的一种,也是猴子的一种,这种关系就和我们接下来要讲的继承是一个道理;
- 在程序里我们将猴子叫做父类(超类,基类),会法术的猴子是他的子类(子类型,派生类),会法术的猴子继承了猴子的所有特征;
- 会法术的猴子是孙悟空的类;孙悟空是会法术的猴子的实例;
-
一旦确定了两个类的继承关系,就包含以以三个意思:
-
子类的实例可以共享父类的方法
-
子类可以覆盖或扩展父类的方法
-
子类和父类都是子类实例的类型
-
2.继承的几种方式
实现继承的方式不止一种。这是因为 JavaScript 中的继承机制并不是明确规定的,而是通过模仿实现的。所以大家看参考书的时候会发现很多种实现继承 的方式,这里我们介绍最常用的几种。
- 对象冒充(构造函数绑定):
原理如下:使用对象冒充(call或apply方法)(实质上是改变了this指针的指向)继承基类。
- 原型链
这种方法更常见,使用prototype属性。
- prototype 对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。
- 原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 prototype 属性。
- 子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。
- 混合方式
我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法
一 .构造函数继承
无参数传递
<script type="text/javascript"> function Monkey(){ this.type="猴子" } function Majic_monkey(){ Monkey.call(this);//对象冒充 this.skill="法术" } var wokong=new Majic_monkey();
//再没有继承的情况下,wokong.type为undefind
alert(wokong.type);
alert(wokong.skill);
</script>
//弹出结果:猴子
法术
有参数传递
<script type="text/javascript"> function Monkey(name,skill){ this.name=name; this.skill=skill; } function Majic_monkey(){ Monkey.call(this,"小米","杀人"); this.tool="大刀" } var people=new Majic_monkey(); alert(people.name+"使用了"+people.tool+"去"+people.skill) </script>
//弹出结果:小米使用了大刀杀人
二 原型链继承
function Monkey(){} Monkey.prototype.name="猴子"; Monkey.prototype.skill="偷桃"; Monkey.prototype.fun=function(){ alert(this.name+this.skill+"很开心"); } function Majic_monkey(){}; Majic_monkey.prototype=new Monkey();
//将Majic_monkey实例指向了Monkey,Majic_monkey可以继承Monkey的属性和方法,同时也可覆盖Monkey的属性和方法 Majic_monkey.prototype.name="孙悟空"; var wokong=new Majic_monkey(); alert(wokong.name); alert(wokong.skill) wokong.fun()
结果:
原型链继承只能是单继承,如果再Majic_monkey继承两个一个父类,则以最后一个父类为主,代码演示如下
function Monkey(){} Monkey.prototype.name="猴子"; Monkey.prototype.skill="偷桃"; Monkey.prototype.fun=function(){ alert(this.name+this.skill+"很开心"); } function AA(){} AA.prototype={ name:"小鱼", skill:"吐泡泡", fun:function(){ alert(this.name+this.skill+"很开心"); } } function Majic_monkey(){}; Majic_monkey.prototype=new Monkey();//继承了Monkey Majic_monkey.prototype=new AA();//继承了AA var wokong=new Majic_monkey(); alert(wokong.name); alert(wokong.skill) wokong.fun()
结果
三 混合模式继承
通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
function Monkey(name,skill){
this.name=name;
this.skill=skill;
}
Monkey.prototype.eat=function(){
alert(this.name+"喜欢"+this.skill)
}
function Min_monkey(){}
Min_monkey.prototype=new Monkey("我","唱歌");//通过父类传参
var wukong=new Min_monkey();
wukong.eat();
function Monkey(name,skill){
this.name=name;
this.skill=skill;
}
Monkey.prototype.eat=function(){
alert(this.name+"喜欢"+this.skill)
}
function Min_monkey(name,skill){
this.name=name;
this.skill=skill;
}
Min_monkey.prototype=new Monkey();
var wukong=new Min_monkey("我","唱歌");//通过子类传参
alert(wukong.name)
wukong.eat();