js中的继承

  说到继承就要用到prototype,用这个方法完成继承的也叫做原型继承,但是在继承中也需你会看到另一种方法,那就是用call来实现的,确实,在某些情况下用call的方式也确实让人感觉这很像继承的东西,但是它们有着本质的区别。而用prototype的原型继承方法才更像是PHP、java等这类面向对象语言中的继承。好了让我们看看它们有什么不同吧!

  首先我们来看call这个函数,在js中有call这个内置的函数(或者叫做方法,反正我喜欢叫函数~哈哈……),它的作用是“调用一个对象的一个方法,以另一个对象替换当前对象”。很绕嘴,当然也很绕脑子,不过我来举个例子就行了:

 1 function add(a,b) 
 2 { 
 3     alert(a+b); 
 4 } 
 5 function sub(a,b) 
 6 { 
 7     alert(a-b); 
 8 } 
 9 
10 add.call(sub,3,1); 

这个例子中就是sub这个方法现在是调用了add这个方法,也就是说add替换了sub完成了a+b这里add.call(sub,3,1)的结果就是4。因为add替换了sub嘛~(那这里是替换啊,也不是继承啊。别着急,接下来再看一个CALL的例子)

 1 function chaolei(){
 2     this.show=function(){
 3         alert("这里显示的是超类的东西!");
 4     };
 5 }
 6 function zilei(name){
 7     this.name=name;
 8         chaolei.call(this);
 9 }
10 var a=new zilei();
11 a.show;

运行结果为:

怎么样,子类调用了父类(这里的父类就是超类!)的方法了吧!这样是不是感觉就像继承了?(别急接下来的实验会颠覆你的思想的!)

那么接下来我们在实验之前要先弄明白继承的一个原理,那就是在面向对象的语言中,如果继承的子类有跟父类相同命名的方法时,这时子类的方法会覆盖父类的方法。当然也可以不覆盖。我们说的是在默认的条件下会这样。

那么明白了这条我们再来看一下下面这个例子吧!

 1 <script type="text/javascript">
 2 function chaolei(){
 3     this.show=function(){
 4         alert("超类");
 5     };
 6 }
 7 function zilei(){
 8     chaolei.call(this);
 9     this.show=function(){
10         alert("子类");
11     };
12 }
13 var a=new zilei();
14 a.show();
15 </script>

运行效果如下:

好像没有什么问题,也符合之前的规定,子类覆盖了父类的方法。的确,这里是没有问题的,但是接下来,我们把chaolei.call(this);这句放到this.show=function(){alert("子类");};这句的下面来看一下:

 1 <script type="text/javascript">
 2  function chaolei(){
 3      this.show=function(){
 4          alert("超类");
 5      };
 6  }
 7  function zilei(){
 8      this.show=function(){
 9          alert("子类");
10      };
11      chaolei.call(this);
12  }
13  var a=new zilei();
14  a.show();
15 </script>

运行结果为:

怎么样,这下子类没有覆盖父类吧!也就不符合我们之前的约定了。所以说用call来完成继承只是看上去比较像而已,而实际的JS看来确有天壤之别!那么怎么才能实现真正的模拟继承呢?下面就是用原型方式来完成继承:

 1 <script type="text/javascript">
 2 function chaolei(){
 3     this.show=function(){
 4         alert("超类");
 5     };
 6 }
 7 function zilei(){
 8     this.show=function(){
 9         alert("子类");
10     };
11 }
12 zilei.prototype=new chaolei(); 
13 zilei.prototype.constructor=zilei;
14 var a=new zilei();
15 a.show();
16 </script>

这里我们用prototype的方式完成了继承,这里的继承可能会有两段迷惑大家的地方,一个就是zilei.prototype=new chaolei();而另一个就是zilei.prototype.constructor=zilei;。prototype这个属性在每个Function中都会有,而通过new这个关键字实例化的对象中就没有这个属性了。我个人的理解就是一个可以为原构造函数添加方法的一个属性,而这里用new chaolei()来作为原函数的方法,就是继承了chaolei()这个类。而下面的constructor也是JS的内置属性,每个Function也都有,是类的构造函数(好像跟上面说的重了,但是我不知道该怎么表达)。这里他的constructor经过上面的zilei.prototype=new chaolei();之后就成了chaolei()了,为了让子类保持原有的constructor。我们在这里再把它的constructor给重新指回zilei(),这样就完成了模拟继承了。可能我这里写的让你感觉有点费解,大家可以看一下链接

http://www.cnblogs.com/qiantuwuliang/archive/2011/01/08/1930548.html或者http://blog.csdn.net/niuyongjie/article/details/4810835

那里比我写的好多了~如果还有不明白的欢迎给我留言,我们一起学习~

原文地址:https://www.cnblogs.com/woshikay/p/3503753.html