Javascript 进阶 继承

目录(?)[+]

转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/29194261
1、基于类的继承
下面看下面的代码:
[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.  <script type="text/javascript">  
  2.   
  3.   
  4.         function Person(name, age)  
  5.         {  
  6.             this.name = name;  
  7.             this.age = age;  
  8.         }  
  9.         Person.prototype.say = function ()  
  10.         {  
  11.             console.log(this.name + " , " + this.age);  
  12.         }  
  13.         function Student(no)  
  14.         {  
  15.             this.no = no;  
  16.         }  
  17. <span style="white-space:pre">    /** 
  18.          * Student的prototype指向Person的对象 
  19.          */</span>  
  20.         Student.prototype = new Person();  
  21.         var stu1 = new Student("0001");  
  22.         stu1.name = '张三';  
  23.         stu1.age = '11';  
  24.         console.log(stu1.no);  
  25.         stu1.say();  
  26.   
  27.   
  28.     </script>  

输出结果:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 0001   
  2. 张三 , 11   

可以看到Student成功集成了Person,并且拥有了Person的say方法,核心代码其实就是一句 Student.prototype = new Person();,下面通过图解来说明原理:


将Student.prototype指向new Person() , new Person的_proto_又指向Person Prototype;这样完成了整个继承。

但是这种方式存在问题:

问题1:当父类存在引用类型变量时,造成数据不一致,下面我们给Person添加一个hobbies属性,类型为数组。

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <script type="text/javascript">  
  2.        /** 
  3.         * 存在问题 
  4.         * 1、无法在Student的构造方法中传递参数用于父类的构造方法 
  5.         * 2、对于引用类型变量,造成数据不一致 
  6.         */  
  7.   
  8.   
  9.        function Person(name, age)  
  10.        {  
  11.            this.name = name;  
  12.            this.age = age;  
  13.            this.hobbies = [] ;  
  14.        }  
  15.        Person.prototype.say = function ()  
  16.        {  
  17.            console.log(this.name + " , " + this.age +" , " +this.hobbies);  
  18.        }  
  19.        function Student(no)  
  20.        {  
  21.            this.no = no;  
  22.        }  
  23.        Student.prototype = new Person();  
  24.   
  25.        var stu1 = new Student("0001");  
  26.        stu1.name = '张三';  
  27.        stu1.age = '11';  
  28.        stu1.hobbies.push("soccer");  
  29.        stu1.say();  
  30.   
  31.        var stu2 = new Student("0002");  
  32.        stu2.name = '李四';  
  33.        stu2.age = '12';  
  34.        stu2.hobbies.push("girl");  
  35.        stu2.say();  
  36.   
  37.    </script>  

输出结果:
[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 张三 , 11 , soccer   
  2. 李四 , 12 , soccer,girl   
可以看出,李四的hobbies应该只有girl,但是上面的代码让所有对象共享了hobbies属性。

上述的继承方式还存在一个问题:

问题2:在Student的构造方法中,无法使用new Student("00001" , "张三" , 12) ;创建对象,并初始化name和age属性,必须stu.name, stu.age进行赋值


为了解决上述问题,对上述代码进行修改:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <script type="text/javascript">  
  2.   
  3.        function Person(name, age)  
  4.        {  
  5.            this.name = name;  
  6.            this.age = age;  
  7.            this.hobbies = [];  
  8.        }  
  9.        Person.prototype.say = function ()  
  10.        {  
  11.            console.log(this.name + " , " + this.age +" , " + this.hobbies);  
  12.        }  
  13.   
  14.        function Student(name, age, no)  
  15.        {  
  16.            /** 
  17.             * 使用call方法,第一个参数为上下文; 
  18.             * 有点类似Java中的super(name,age)的感觉 
  19.             */  
  20.            Person.call(this, name, age);  
  21.            this.no = no;  
  22.        }  
  23.   
  24.        Student.prototype = new Person();  
  25.   
  26.        var stu1 = new Student("0001","张三",11);  
  27.        stu1.hobbies.push("soccer");  
  28.        stu1.say();  
  29.   
  30.        var stu2 = new Student("0002","李四",12);  
  31.        stu2.hobbies.push("cangjin");  
  32.        stu2.hobbies.push("basketball");  
  33.        stu2.say();  
  34.   
  35.    </script>  

输出:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 0001 , 张三 , soccer   
  2. 0002 , 李四 , cangjin,basketball   

在Student的构造方法中使用了Person.call(this,name,age)感觉就像super(name,age)【call的第一个参数为上下文】;并且成功解决了对引用属性的共享问题,完美解决。

2、基于原型链的继承

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <script type="text/javascript">  
  2.   
  3.     /** 
  4.      * 基于原型链的集成中都是对象 
  5.      * 存在问题: 
  6.      * 1、对于引用类型变量,造成数据不一致 
  7.      */  
  8.     var Person = {  
  9.                 name: "人",  
  10.                 age: 0,  
  11.                 hobbies: [],  
  12.                 say: function ()  
  13.                 {  
  14.                     console.log(this.name + " , " + this.age + " , " + this.hobbies);  
  15.                 }  
  16.             }  
  17.             ;  
  18.   
  19.     var Student = clone(Person);  
  20.     Student.no ="";  
  21.     Student.sayHello = function()  
  22.     {  
  23.         console.log(this.name  +"hello ") ;  
  24.     }  
  25.   
  26.     var stu1 = clone(Student);  
  27.     stu1.name = "zhangsan";  
  28.     stu1.age = 12;  
  29.     stu1.hobbies.push("Java");  
  30.     stu1.say();  
  31.   
  32.     var stu2 = clone(Student);  
  33.     stu2.name = "lisi";  
  34.     stu2.age = 13;  
  35.     stu2.hobbies.push("Javascript");  
  36.     stu2.say();  
  37.   
  38.     /** 
  39.      * 返回一个prototype执行obj的一个对象 
  40.      * @param obj 
  41.      * @returns {F} 
  42.      */  
  43.     function clone(obj)  
  44.     {  
  45.         var F = function ()  
  46.         {  
  47.         };  
  48.         F.prototype = obj;  
  49.         return new F();  
  50.   
  51.     }  
  52.   
  53.   
  54. </script>  

输出:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. zhangsan , 12 , Java   
  2. lisi , 13 , Java,Javascript   

可以看出同样存在引用属性不一致的问题,并且整个操作全部基于对象,给人的感觉不是很好,下面通过图解解释下原理:


对象间通过一个clone函数,不断的返回一个新的对象,且prototype执行传入的对象,整个继承过程其实就是_proto_不断的指向,形成一个链,所以叫做原型链。


好了,已经介绍完了,js的两种集成的方式,最好使用的还是通过类的继承(上述第一种方案,解决存在问题的)。



如果代码或者讲解存在任何问题,欢迎留言指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值