说到继承就要用到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
那里比我写的好多了~如果还有不明白的欢迎给我留言,我们一起学习~