探讨 JS 的面向对象中继承的那些事

Posted developerl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探讨 JS 的面向对象中继承的那些事相关的知识,希望对你有一定的参考价值。

最近学了 JS 的面向对象,这篇文章主要是探讨 JS 的面向对象中继承的那些事。

 

JS中继承的特点:

1、子类继承父类;

2、子类可以用父类的方法和属性

3、子类的改变可以不影响父类

 

下面用一个例子来说明 JS 的继承

这段代码创建了一个父类以及它的原型,同时还创建了一个子类,并继承了父类的私有属性

 1 <script>
 2         //这是父类
 3         function Father(name,age,marry){
 4             this.name=name;
 5             this.age=age;
 6             this.marry=marry;
 7         }
 8         //父类的原型
 9         Father.prototype.showName=function(){
10             alert(this.name);
11         }
12 
13         //子类
14         function Son(name,age,marry,weight){
15             Father.call(this,name,age,marry);
16             this.weight=weight;
17         }
18         
19  </script>

当子类Son想继承父类的原型时,我的做法一开始是这么做的

 1 <script>
 2         //这是父类
 3         function Father(name,age,marry){
 4             this.name=name;
 5             this.age=age;
 6             this.marry=marry;
 7         }
 8         //父类的原型
 9         Father.prototype.showName=function(){
10             alert(this.name);
11         }
12 
13         //子类
14         function Son(name,age,marry,weight){
15             Father.call(this,name,age,marry);
16             this.weight=weight;
17         }
18         
19         //错误的做法
20         Son.prototype=Father.prototype;
21         Son.prototype.showAge=function(){
22             alert(this.age);
23         }
24         var father=new Father(‘王大锤‘,30,true);
25         alert(father.showAge);
26         
27 </script>

技术分享图片

运行的结果可以发现,子类原型的改变影响了父类的原型,父类的原型中本来是没有showAge方法的,这就违背了前面继承的第三个特点了。

分析原因:上面代码的第20行  Son.prototype=Father.prototype;这里的 ‘=‘ 两边都是对象,那么它代表的意思就是引用,如果是引用的话,左边的对象改变,肯定会影响了右边的对象

      所以才出现了子类原型的改变影响了父类的原型。

解决办法

方法一:核心思路,前面的问题不是说 ‘=‘ 是引用的关系才导致问题的嘛,那这里就保证 ‘=‘ 永远是赋值的关系,而不是引用。这里就定义一个 Clone() 方法,将父类对象拷贝给子类。

    Clone() 方法里用到递归的原因是,在拷贝的过程中对象中可能嵌套对象。

 

 1 <script>
 2         //这是父类
 3         function Father(name,age,marry){
 4             this.name=name;
 5             this.age=age;
 6             this.marry=marry;
 7         }
 8         //父类的原型
 9         Father.prototype.showName=function(){
10             alert(this.name);
11         }
12 
13         //子类
14         function Son(name,age,marry,weight){
15             Father.call(this,name,age,marry);
16             this.weight=weight;
17         }
18         Son.prototype=new Clone(Father.prototype);
19         Son.prototype.showAge=function(){
20             alert(this.age);
21         }
22         var father=new Father(‘王大锤‘,30,true);
23         alert(father.showAge);
24 
25         //通过克隆对象:核心思路是保证 ‘=‘ 是赋值的关系,而不是引用,也就是保证 ‘=‘ 的右边不是对象
26         function Clone(obj){
27             for(var i=0;i<obj.length;i++){
28                 if(typeof(obj[key]==‘object‘)){
29                     this.key=new Clone(obj[key]);
30                 }else{
31                     this.key=obj[key];
32                 }
33             }
34         }  
35 </script>

 

技术分享图片

 

 这时候的结果父类对象的showAge方法是undefined

 

方法二:代码很简单,但是很难想到,没有第一个方法那么好理解。核心思想:对象自身属性的改变,不会影响其构造函数的属性的改变。

 1 <script>
 2         //这是父类
 3         function Father(name,age,marry){
 4             this.name=name;
 5             this.age=age;
 6             this.marry=marry;
 7         }
 8         //父类的原型
 9         Father.prototype.showName=function(){
10             alert(this.name);
11         }
12 
13         //子类
14         function Son(name,age,marry,weight){
15             Father.call(this,name,age,marry);
16             this.weight=weight;
17         }
18         function fn(){}
19         fn.prototype=Father.prototype;
20         Son.prototype=new fn();      
21         Son.prototype.showAge=function(){
22             alert(this.age);
23         }
24         var father=new Father(‘王大锤‘,30,true);
25         alert(father.showAge);
26 
27         //通过克隆对象:核心思路是保证 ‘=‘ 是赋值的关系,而不是引用,也就是保证 ‘=‘ 的右边不是对象
28         // Son.prototype=new Clone(Father.prototype);
29         // function Clone(obj){
30         //     for(var i=0;i<obj.length;i++){
31         //         if(typeof(obj[key]==‘object‘)){
32         //             this.key=new Clone(obj[key]);
33         //         }else{
34         //             this.key=obj[key];
35         //         }
36         //     }
37         // }  
38 </script>

技术分享图片

 

以上是关于探讨 JS 的面向对象中继承的那些事的主要内容,如果未能解决你的问题,请参考以下文章

面向对象中继承的例题(运算方法)

java中继承的好处是啥,在组合和继承中该如何取舍?

面向对象的三大特性之继承-基础知识总结------彭记(05)

ES5和ES6中继承的不同之处

js 继承概述

js中继承的实现,原型链的知识点归纳,借用构造函数,组合继承(伪经典继承)