• javascript——面向对象程序设计(4)


      1     <script type="text/javascript">
      2         //1、继承
      3         //2、原型链
      4         //3、借用构造函数
      5         //4、组合继承
      6         //5、原型式继承
      7         //6、寄生式继承
      8         //7、寄生组合式继承
      9 
     10         //1、继承是OO中最让人津津乐道的概念。许多OO语言都支持两种继承方式:接口继承和实现继承。
     11         //接口继承只支持方法签名,而实现继承则继承实际的方法。
     12         //由于函数没有签名,所以在ECMAScript中无法实现接口继承,只支持实现继承,而且其实现继承主要由原型链来实现。
     13 
     14         //2、原型链。
     15         //简单回顾一下,构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针
     16         //而实例都包含一个指向原型对象的内部指针。
     17         //而如果我们让原型对象指向另一个类型的实例,结果会怎样呢?显然,此时的原型对象将包含一个指向另一个原型的指针,
     18         //相应的,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,
     19         //就构成了实例与原型的链条。这就是所谓原型链的基本概念。eg:
     20 
     21         //动物类
     22         function Animal() {
     23             this.shout = "不知道";
     24         }
     25         Animal.prototype.getAnimalValue = function () {
     26             return this.shout;
     27         }
     28 
     29         //狗狗类
     30         function Dog() {
     31             this.dogShout = "汪汪汪~";
     32         }
     33 
     34         ///狗狗类继承动物类
     35         Dog.prototype = new Animal();
     36 
     37         Dog.prototype.getDogValue = function () {
     38             return this.dogShout;
     39         }
     40 
     41         var instance = new Dog();
     42         //狗狗类调用动物类叫的方法
     43         alert(instance.getAnimalValue())
     44         //instance.getAnimalValue()会经历3个步骤,1、搜索实例 2、搜索Dog.prototype 3、搜索Animal.prototype
     45         //a、别忘记默认的原型。大家要记住,所有的函数的默认原型都是Object的实例,因此默认原型都会有一个内部指针,
     46         //指向Object.prototype。这也正是自定义类都会继承toString()和valueOf()的方法的根本原因
     47 
     48 
     49         //b、确定原型和实例的关系
     50         alert(instance instanceof Object);//true
     51         alert(instance instanceof Animal);//true
     52         alert(instance instanceof Dog);//true
     53 
     54 
     55         alert(Object.prototype.isPrototypeOf(instance));//true
     56         alert(Animal.prototype.isPrototypeOf(instance));//true
     57         alert(Dog.prototype.isPrototypeOf(instance));//true
     58 
     59         //c、原型链的问题
     60         //想必大家还记得,前面介绍过含引用类型值的原型会被所有的实例共享,
     61         //这也是为什么要在构造函数中,而不是在原型对象中定义属性的原因。
     62         //所以,实践中很少有人单独使用原型链。
     63 
     64 
     65         //3、借用构造函数(又叫:伪造对象或经典继承)
     66         //这种继承的方式很简单,就是在子类构造函数内部调用超类构造函数使用call或apply
     67         function Animal() {
     68             this.colors = ['red', 'blue', 'green'];
     69         }
     70 
     71         function Dog() {
     72             //继承了Animal类
     73             Animal.call(this);
     74         }
     75 
     76         var dog = new Dog();
     77         dog.colors.push("black");
     78         alert(dog.colors);//'red','blue','green','black'
     79 
     80         var dog2 = new Dog();
     81         alert(dog2.colors);//'red','blue','green'
     82 
     83         //相对于原型链而言,借用构造函数有很大的优势,即可以在子类构造函数中向超类传递参数
     84         function Animal2(name) {
     85             this.name = name;
     86         }
     87 
     88         function Dog2() {
     89             //继承了Animal类
     90             Animal2.call(this, "大黄");
     91             this.age = 2;
     92         }
     93 
     94         var dog = new Dog2();
     95         alert("年龄:" + dog.age + ",名称:" + dog.name);
     96 
     97         //因为方法都在构造函数中定义,因此函数复用就无从谈起了。而且在超类原型中定义的方法,对于子类型而言也是不可见的
     98         //结果所有类型都只能使用构造函数模式。
     99         //考虑到这些问题,借用构造函数的技术也很少单独使用。
    100 
    101         //4、组合继承
    102         function Animal3(name) {
    103             this.name = name;
    104             this.colors = ['red', 'blue', 'green'];
    105         }
    106 
    107         Animal3.prototype.sayName = function () {
    108             alert(this.name)
    109         }
    110 
    111         function Dog3(name, age) {
    112             //继承属性
    113             Animal3.call(this, name);
    114             this.age = age;
    115         }
    116         //继承方法
    117         Dog3.prototype = new Animal3();
    118         Dog3.prototype.constructor = Dog3;
    119         Dog3.prototype.sayAge = function () {
    120             alert(this.age)
    121         }
    122 
    123         var d3 = new Dog3("小黄", 1);
    124         d3.colors.push("black");
    125         alert(d3.colors);//red,blue,green,black
    126         d3.sayAge();//1
    127         d3.sayName();//小黄
    128 
    129         //组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为javascript中最常用继承方式
    130         //而且instanceof 和 isPrototypeOf也能够用于识别基于组合继承创建的对象。
    131 
    132         //5、原型式继承
    133         //在没有必要兴师动众的创建构造函数,而只想让一个对象与另一个对象保持类似的情况下,原型式继承是完全可以胜任的
    134         //不过别忘了:包含引用类型的值的属性始终都会共享相应的值,就像使用原型模式一样。
    135 
    136         var Person={
    137             name:'xulei',
    138             friends:['张三','李四','王五']
    139         }
    140 
    141         var p1=Object.create(Person);
    142         p1.name="徐磊1";
    143         p1.friends.push("killey");
    144         var p2=Object.create(Person);
    145         p2.name="徐磊2";
    146         p2.friends.push("jack");
    147 
    148 
    149         alert("p1.name:"+p1.name);//徐磊1
    150         alert("p1.friends:"+p1.friends);//张三','李四','王五','killey','jack'
    151         alert("p2.name:"+p2.name);//徐磊2
    152         alert("p2.friends:"+p2.friends);//张三','李四','王五','killey','jack'
    153 
    154 
    155         //6、寄生式继承
    156         //寄生式继承是与原型式继承紧密相关的一种思路。寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数
    157         //该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。eg:
    158         function object(o) {
    159             function F() { }
    160             F.prototype=o;
    161             return new F();
    162         }
    163         function createAnother(original){
    164             var clone=object(original);//通过调用函数来创建一个新对象
    165             clone.sayHi=function(){//以某种方式来增强这个对象
    166                 alert("hi");
    167             };
    168             return clone;//返回这个对象
    169         }
    170         var Person2={
    171             name:'xulei',
    172             friends:['张三','李四','王五']
    173         }
    174 
    175         var p3=createAnother(Person2);
    176         p3.sayHi();
    177 
    178 
    179         //7、寄生组合式继承
    180         //前面说过,组合继承是最常用继承模式,不过它也有自己的不足。
    181         //组合继承最大的问题就是无论在什么情况下,都会调用两次超类型的构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部
    182         //eg:
    183         function SuperType(name){
    184             this.name=name;
    185             this.colors=['red','blue','green'];
    186         }
    187 
    188         SuperType.prototype.sayName=function(){
    189             alert(this.name);
    190         }
    191 
    192         function SubType(name,age) {
    193             SuperType.call(this,name);//第二次调用SuperType
    194             this.age=age;
    195         }
    196 
    197         SubType.prototype=new SuperType();//第一次调用SuperType
    198         SubType.prototype.constructor=SubType;
    199         SubType.prototype.sayAge=function(){
    200             alert(this.age);
    201         }
    202 
    203         //好在已经有更好的解决方案————寄生组合式继承
    204         //所谓寄生组合式继承就是借用构造函数来继承属性,通过原型链的混成形式来继承方法。
    205         //其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非是超类型原型的一个副本而已
    206         //本质上,就是使用寄生继承来继承超类型的原型,然后再将结果指定给子类型的原型。eg:
    207         function object(o) {
    208             function F() { }
    209             F.prototype=o;
    210             return new F();
    211         }
    212         function inheritPrototype(subType,superType) {
    213             var prototype=object(superType.prototype);//创建对象
    214             prototype.constructor=subType;//增强对象
    215             subType.prototype=prototype;//指定对象
    216         }
    217 
    218         function SuperType(name){
    219             this.name=name;
    220             this.colors=['red','blue','green'];
    221         }
    222 
    223         SuperType.prototype.sayName=function(){
    224             alert(this.name);
    225         }
    226 
    227         function SubType(name,age) {
    228             SuperType.call(this,name);
    229             this.age=age;
    230         }
    231         inheritPrototype(SubType,SuperType);
    232         SubType.prototype.sayAge=function(){
    233             alert(this.age);
    234         }
    235 
    236         var p4=new SubType("张三",29);
    237         p4.sayName();
    238         //这个例子的高效率体现在它只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype上创建不必要的、多余的属性
    239         //与此同时,原型链还能保持不变;因此还能正常的使用instanceOf 和isPrototypeOf
    240         //普遍认为寄生组合继承是引用类型最理想的继承方式。
    241 
    242 
    243 
    244 
    245 
    246     </script>
  • 相关阅读:
    你可能不知道的Linux/GNU bash sort多列排序功能
    设置字间距
    设置为灰度图
    点击短信中的url打开某个应用
    AchartEngine绘图引擎
    表格类似Excel
    自定义圆环progressbar
    高低版本方法兼容
    读取并创建excel文件(.xls)
    在android studio中导入github下载的工程
  • 原文地址:https://www.cnblogs.com/goesby/p/4264347.html
Copyright © 2020-2023  润新知