zoukankan      html  css  js  c++  java
  • 面向对象与原型---继承

    继承是面向对象中一个比较核心的概念。其他正统面向对象语言都会用两种方式实现继
    承:一个是接口实现,一个是继承。而ECMAScript 只支持继承,不支持接口实现,而实现
    继承的方式依靠原型链完成。

    一、原型+对象构造之间的关系结构像链条一样,称原型链。

    function Box() { //Box 构造/、被继承的函数叫做超类型(父类,基类)
    this.name = 'Lee';
    }
    function Desk() { //Desk 构造//继承的函数叫做子类型(子类或派生类)
    this.age = 100;
    }
    function Table() {
        this.level = 'AAAAA';
    }
    //通过原型链继承,超类型实例化后的对象实例,赋值给子类型的原型属性
    //new Box()会将Box构造里的信息和原型里的信息都交给Desk
    //Desk的原型,得到的是Box的构造+原型里的信息
    Desk.prototype = new Box();
    Table.prototype = new Desk();

    如果要实例化table,那么Desk 实例中有age=100,原型中增加相同的属性age=200,
    最后结果是多少呢?
    Desk.prototype.age = 200; //实例和原型中均包含age
    PS:以上原型链继承还缺少一环,那就是Obejct,所有的构造函数都继承自Obejct。而
    继承Object 是自动完成的,并不需要程序员手动继承。

    从属关系

    function Box() {                    //被继承的函数叫做超类型(父类,基类)
        this.name = 'Lee';
    }
    
    Box.prototype.name = 'Jack';
    
    function Desk() {                //继承的函数叫做子类型(子类,派生类)
        this.age = 100;
    }
    
    Desk.prototype = new Box();        //通过原型链继承
    
    var box = new Box();
    var desk = new Desk();
    //alert(desk.name);                    //就近原则,实例里有,就返回,没有就去查找原型
    
    //子类型从属于自己或者他的超类型
    //alert(desk instanceof Object);
    alert(desk instanceof Desk);
    alert(desk instanceof Box);
    alert(box instanceof Desk);

    字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数

    二、对象冒充(伪造对象、经典继承)/借用构造函数

    //使用对象冒充继承
    
    function Box(name, age) {
        this.name = name;
        this.age = age;
        this.family = ['哥哥','姐姐','妹妹'];    //引用类型,放在构造里就不会被共享 
    }
    
    //Box.prototype.family = '家庭';
    
    function Desk(name, age) {
        Box.call(this, name, age)                //对象冒充,对象冒充只能继承构造里的信息//desk冒充Box
    }
    
    
    var desk = new Desk('Lee', 100);
    alert(desk.family);
    desk.family.push('弟弟');
    alert(desk.family);
    
    
    var desk2 = new Desk('Lee', 100);
    alert(desk2.family);

    三、借用构造函数虽然解决了刚才两种问题,但没有原型,复用则无从谈起。所以,我们需
    要原型链+借用构造函数的模式,这种模式成为组合继承。(用的比较多)

    function Box(name, age) {
        this.name = name;
        this.age = age;
        this.family = ['哥哥','姐姐','妹妹'];
    }
    
    Box.prototype.run = function () {
        return this.name + this.age + '运行中...';
    };
    
    //构造函数里的方法,放在构造里,每次实例化,都会分配一个内存地址,浪费,所以最好放在原型里,保证多次实例化只有一个地址
    
    function Desk(name, age) {
        Box.call(this, name, age)                    //对象冒充
    }
    
    Desk.prototype = new Box();                //原型链继承
    
    
    var desk = new Desk('Lee', 100);
    alert(desk.run());

    四、原型继承

    原型式继承;这种继承借助原型并基于已有的对象创建新对象,同时还不必因此创建自定义类型。

    //1.原型链继承,2.借用构造函数继承(对象冒充继承) 3.组合继承(结合前两种)
    //4.原型式继承
    
    //临时中转函数
    function obj(o) {                //o表示将要传递进入的一个对象 
        function F() {}                //F构造是一个临时新建的对象,用来存储传递过来的对象
        F.prototype = o;            //将o对象实例赋值给F构造的原型对象
        return new F();            //最后返回这个得到传递过来对象的对象实例
    }
    
    //F.prototype = o 其实就相当于 Desk.prototype = new Box();
    
    
    //这是字面量的声明方式,相当于var box = new Box();
    var box = {
        name : 'Lee',
        age : 100,
        family : ['哥哥','姐姐','妹妹']
    };
    
    //box1就等于new F()
    var box1 = obj(box);
    //alert(box1.name);
    alert(box1.family);
    box1.family.push('弟弟');
    alert(box1.family);
    
    var box2 = obj(box);
    alert(box2.family);                    //引用类型的属性共享了

    五、寄生式继承把原型式+工厂模式结合

    目的是为了封装创建对象的过程。

    //临时中转函数
    function obj(o) {                
        function F() {}                
        F.prototype = o;            
        return new F();            
    }
    
    //寄生函数
    function create(o) {
        var f = obj(o);
        f.run = function () {
            return this.name + '方法';
        }
        return f;
    }
    
    var box = {
        name : 'Lee',
        age : 100,
        family : ['哥哥','姐姐','妹妹']
    };
    
    
    var box1 = create(box);
    alert(box1.run());

    六、寄生组合继承

    组合式继承是JavaScript 最常用的继承模式;但,组合式继承也有一点小问题,就是超
    类型在使用过程中会被调用两次:一次是创建子类型的时候,另一次是在子类型构造函数的
    内部。

    //临时中转函数
    function obj(o) {                
        function F() {}                
        F.prototype = o;            
        return new F();            
    }
    
    
    //寄生函数
    function create(box, desk) {
        var f = obj(box.prototype);
        f.constructor = desk;                //调整原型构造指针
        desk.prototype = f;
    }
    
    function Box(name, age) {
        this.name = name;
        this.age = age;
    }
    
    Box.prototype.run = function () {
        return this.name + this.age + '运行中...'
    }
    
    function Desk(name, age) {
        Box.call(this, name, age);                //对象冒充
    }
    
    //通过寄生组合继承来实现继承
    create(Box, Desk);                            //这句话用来替代Desk.prototype = new Box();
    
    
    var desk = new Desk('Lee', 100);
    alert(desk.run());
    alert(desk.constructor);
    本人无商业用途,仅仅是学习做个笔记,特别鸣谢小马哥,学习了IOS,另日语学习内容有需要文本和音频请关注公众号:riyuxuexishuji
  • 相关阅读:
    POJ -- 3468
    HDOJ--1698
    简单的API应用
    Linux引导流程
    Python 实现网络爬虫小程序
    codeforce
    Count the string -- HDOJ 3336
    初次运行 Git 前的配置
    leetcode244- Shortest Word Distance II- medium
    leetcode243- Shortest Word Distance- easy
  • 原文地址:https://www.cnblogs.com/laugh/p/4358576.html
Copyright © 2011-2022 走看看