• 面向对象与原型(三)


    继承:

          继承是面向对象中一个比较核心的概念。其他正统面向对象语言都会用两种方式实现继

    承: 一个是接口实现, 一个是继承。 而ECMAScript只支持继承, 不支持接口实现,而实

    现继承的方式依靠原型链完成。

           function Box(){                       //Box构造
                 this.name='Lee';
           }
           function Desk(){                    //Desk构造
                 this.age=100;
           }
           Desk.prototype=new Box();           //Desc继承了Box, 通过原型, 形成链条
           var desk=new Desk();
           alert(desk.age);
           alert(desk.name);              //得到被继承的属性
           function Table(){               //Table构造
                 this.level='AAAAA';
           }
          Table.prototype=new Desk(); //继续原型链继承
          var table=new Table();
          alert(table.name);               //继承了Box和Desk

                                                     原型链继承图

          在JavaScript里,被继承的函数称为超类型(父类,基类也行,其他语言叫法),继承的函数称为

    子类型(子类,派生类)。继承也有之前问题,比如字面量重写原型会中断关系, 使用引用类型的原型

    ,并且子类型还无法给超类型传递参数。为了解决引用共享和超类型无法传参的问题,我们采用一种

    叫借用构造函数的技术,或者成为对象冒充(伪造对象、经典继承)的技术来解决这两种问题。

          function Box(age){

                this.name=['Lee','Jack','Hello']

                this.age=age;

          }

          function Desk(age){

                Box.call(this,age);       //对象冒充,给超类型传参

          }

          var desk = new Desk(200);

          alert(desk.age);

          alert(desk.name);

          desk.name.push('AAA');    //添加的新数据,只给 desk

          alert(desk.name);

          借用构造函数虽然解决了刚才两种问题, 但没有原型, 复用则无从谈起。 所以, 我们需要

    原型链+借用构造函数的模式,这种模式成为组合继承。

          function Box(age) {

                this.name = ['Lee', 'Jack', 'Hello']

                this.age = age;

         }

         Box.prototype.run = function () {

               return this.name + this.age;

         };

         function Desk(age) {

               Box.call(this, age); //对象冒充

         }

         Desk.prototype = new Box(); //原型链继承

         var desk = new Desk(100);

         alert(desk.run());

         还有一种继承模式叫做:原型式继承;这种继承借助原型并基于已有的对象创建新对象,

    同时还不必因此创建自定义类型。

          function obj(o) { //传递一个字面量函数

                function F() {} //创建一个构造函数

                F.prototype = o; //把字面量函数赋值给构造函数的原型

                return new F(); //最终返回出实例化的构造函数

          }

          var box = { //字面量对象

               name : 'Lee',

               arr : ['哥哥','妹妹','姐姐']

           };

           var box1 = obj(box); //传递

           alert(box1.name);

           box1.name = 'Jack';

           alert(box1.name);


           alert(box1.arr);

           box1.arr.push('父母');

           alert(box1.arr);

           var box2 = obj(box); //传递

           alert(box2.name);

           alert(box2.arr); //引用类型共享了

           寄生式继承把原型式+工厂模式结合而来,目的是为了封装创建对象的过程。

           function create(o) { //封装创建过程

                 var f= obj(o);

                 f.run= function () {

                       return this.arr; //同样,会共享引用

                 };

                 return f;

            }

          组合式继承是 JavaScript最常用的继承模式; 但, 组合式继承也有一点小问题, 就是超

    型在使用过程中会被调用两次: 一次是创建子类型的时候, 另一次是在子类型构造函数的部。

          function Box(name) {

                this.name = name;

                this.arr = ['哥哥','妹妹','父母'];

          }

          Box.prototype.run= function() {

                returnthis.name;

          };

          function Desk(name, age) {

                Box.call(this, name); //第二次调用 Box

                this.age = age;

          }

          Desk.prototype = newBox(); //第一次调用 Box

          以上代码是之前的组合继承,那么寄生组合继承,解决了两次调用的问题。

          function obj(o) {

                functionF() {}

                F.prototype= o;

                return new F();

          }

          function create(box,desk){

                var f=obj(box.prototype);

                f.constructor=desk;

                desk.prototype=f;

          }

          function Box(name){

                this.name=name;

                this.arr=['哥哥','妹妹','父母'];

          }

          Box.prototype.run=function(){

                return this.name;

          };

          function Desk(name,age){

                Box.call(this,name);

                this.age=age;

           }

           create(Box,Desk); //通过这里实现继承

           var desk=new Desk('Lee',100);

           desk.arr.push('姐姐');

           alert(desk.arr);

           alert(desk.run()); //只共享了方法

           var desk2=new Desk('Jack',200);

           alert(desk2.arr); //引用问题解决

  • 相关阅读:
    高性能解决线程饥饿的利器 StampedLock
    月初刚拿到美团offer,新鲜的美团现场面试41题(三面技术+HR面)
    这两份Java“并发+异步”编程宝典,堪称编程界的“瑰宝”
    阿里架构师的学习笔记:多线程+JVM+Mysql+Redis+设计模式
    打造多模块+高可用+高扩展Spring Cloud版分布式电商项目源码分享
    想要彻底搞懂微服务架构必先学:SpringBoot+SpringCloud+docker
    厉害了!阿里P8手写《springboot 核心》PDF来了
    阿里P8熬夜总结Spring源码笔记,上线3分钟“全网跪求”
    UFLDL课程学习(二)
    UFLDL课程学习(一)
  • 原文地址:https://www.cnblogs.com/xbj-2016/p/5127757.html
Copyright © 2020-2023  润新知