• javascript中的继承[四] 总结(《ObjectOriented JavaScript》第六章)


    前面两章中提到的实现继承的方法,都是《Object-Oriented JavaScript》第六章提及的,书中最后也做了总结:

    In this chapter you learned quite a few ways (patterns) for implementing inheritance.

    The different types can roughly be divided into:

    1. Patterns that work with constructors
    2. Patterns that work with objects

    You can also classify the patterns based on whether they:

    1. Use the prototype
    2. Copy properties
    3. Do both (copy properties of the prototype)

         第六章介绍了一些继承的方法,分为两模式:

            基于构造函数生成对象的模式

            直接继承对象的模式

        也可以按照另一种思路分类:

            使用了原型prototype

            复制属性

            复制原型的属性

    可以说,这是实现继承的最核心的内容,实践中常常交错在一起。回顾下前文介绍的基本继承方式:

    //构造函数 使用原型链
    Coder.prototype = new Person("无名");
    //构造函数 共享原型链 Coder.prototype
    = Person.prototype;
    //构造函数 使用原型链 只继承原型属性方法 function extend(Child,Parent){
    var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; }
    //构造函数 使用原型链 复制原型属性 function extend2(Child,Parent){
    var p = Parent.prototype; var c = Child.prototype; for(var i in p){ c[i] = p[i]; } }
    //继承对象 复制属性 function extendCopy(p, c){
    var c = c || {}; for(var i in p){ c[i]=p[i]; } return c; }
    //继承对象 深复制 function deepCopy(){}
    //继承对象 使用原型链 function
    object(o){ function F(){}; F.prototype = o; return new F(); }
    //继承对象 使用原型链 复制属性 function objectPlus(o, stuff){}
    //继承对象 复制属性 function multi(){}

    遗留的一些事情

    1.之前的文章中出现以下代码

    function Person(name){
        this.name = name;
    }
    Person.prototype.sayHello = function(){
        alert(this.name);
    };
    
    function Coder(name,language){
       this.language = language;
           this.name = name;
    }
    
    Coder.prototype = new Person("无名");
    Coder.prototype.constructor = Coder;
    Coder.prototype.code = function(){
        alert("i am a "+this.language+" coder");
    };

    我们改造下这段代码,主要解决子类调用父类的构造函数中初始化代码,自行对比优缺点:

    function Person(name){
        this.name = name;
    }
    Person.prototype.sayHello = function(){
        alert(this.name);
    };
    
    function Coder(name,language){
           Person.apply(this,arguments);
       this.language = language;
    }
    
    extend2(Coder,Person);
    Coder.prototype.code = function(){
        alert("i am a "+this.language+" coder");
    };

    通过 Person.apply(this,arguments)调用父类的构造方法,extend2继承父类的原型方法,最后再扩展原型方法。

    如果扩展的原型方法很多,我想你一定有办法知道如果通过之前的基础方法,写出一个新的符合你自己要求的继承机制。

    我们完全可以写一个 extend3(Coder,Person,stuff)的方法~如果你有需要这么做的话。

    2.几个函数操作

    obj instanceof F // 判断对象obj是否是F的实例

    F.prototype.isPrototypeOf(obj)//作用同上

    obj.constructor // 返回obj的构造函数 

    obj.hasOwnProperty('属性名') // 判断obj是否有属于自己的属性,而不是他所指原型的属性

    这几个操作帮助理解原型链、继承过程,在实践中也有很重要的作用。

    3.关于 子“类”调用父"类"的方法、属性

    有三个类 Shape TwoDShape Triangle 形状、2D形状、三角形,他们继承关系。

    对象实例需要实现一种方法:toString() 不仅要输出自己的类名,还要输出祖辈的类名。

    如何实现呢?

    由于继承的实现方式挺多的,而且子“类”的这种需求千变万化,如何有效控制,文章(本人能力有限)一句话说不清楚,《o-o》中也只是穿插地说了一下。

    基本的一种思路是 在 Parent加一个静态属性uber指向Child.prototype

    
    
    function extend(Child,Parent){
        var F = function(){};
        F.prototype = Parent.prototype;
        Child.prototype = new F();
    Child.prototype.constructor
    = Child;

    Child.uber = Parent.prototype;
    }


    function
    Shape(){}; Shape.ptototype.name = "shape"; Shape.prototype.toString = function(){ var result = []; if(this.constructor.uber){ result[result.length] = this.constructor.uber.toString(); } result[result.length] = this.name; return result.join(', '); }; function TwoDShape(){}; extend(TwoDShape,Shape); TwoDshape.prototype.name = "2dShape"; function Triangle(side, height){ this.side = side; this.height = height; }; extend(Triangle, TwoDShape); Triangle.prototype.name = "triangle"; Triangle.prototype.getArea = function(){return this.side*this.height/2;}; var my = new Triangle(3,4); my.toString();

    复制原型属性的时候

    function extend2(Child,Parent){
        var p = Parent.prototype;
        var c = Child.prototype;
        for(var i in p){
            c[i] = p[i];
        }
        c.uber = p;
    }

    对象直接继承的时候

    function object(o){
        var n;
        function F(){}
        F.prototype = o;
        n = new F();
        n.uber = o;
        return n;
    
    }

    上面的实现 都是 《o-o》第六章中提及的

    实例、原型、构造函数  谁可以最直接地调用方法uber ,以及要产生什么效果,按需实现。

    uber 是源于德语,super是js中的一个关键词,因此建议使用uber

    到此,《o-o》第六章的内容都介绍完毕,内容基于自己的梳理,增加了自己的理解,难免有疏漏之处,请指正。

    欢迎大家看原著,国内也出了翻译版~




    苦逼码农一个,
    人力资源管理专业本科毕业,
    懂点c#,
    懂点javascript,
    懂点sql,
    懂点设计模式
    ...

    @我是赵六六

    q:329952402

  • 相关阅读:
    PHP 反射 ReflectionClass
    go-字符串生成数据库字段
    grpc类型
    ubuntu安装zookeeper集群
    ubuntu安装JDK
    zookeeper分布式读写锁
    golang利用gob序列化struct对象保存到本地(转载)
    golang手动管理内存(转载)
    类json格式字符串打印
    研二寒假---关于Qt&CV曲线算法问题
  • 原文地址:https://www.cnblogs.com/acjialiren/p/2984258.html
Copyright © 2020-2023  润新知