• 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>
  • 相关阅读:
    flock对文件锁定读写操作的问题 简单
    hdu 2899 Strange Fuction(二分)
    hdu 2199 Can you solve this equation? (二分)
    poj 3080 Blue Jeans (KMP)
    poj 2823 Sliding Window (单调队列)
    poj 2001 Shortest Prefixes (trie)
    poj 2503 Babelfish (trie)
    poj 1936 All in All
    hdu 3507 Print Article (DP, Monotone Queue)
    fzu 1894 志愿者选拔 (单调队列)
  • 原文地址:https://www.cnblogs.com/goesby/p/4264347.html
Copyright © 2020-2023  润新知