• 面向对象——构造函数的继承


        

    面向对象分为封装继承,之前介绍了如何"封装"数据和方法,以及如何从原型对象生成实例,今天来详细看一下面向对象里面的构造       函数继承

        今天要介绍的是,对象之间的"继承"的五种方法。

    1.首先我们定义俩个构造函数,    

    //比如有一猫的构造函数;
    function Animal (){
        this.species = "动物";
    }
    //还有一个猫的构造函数
    function Cat (name,color){
        this.name = name;
        this.color = color;
    }
        

    2.第一种方法  call apply 方法继承;

    function Animal (){
        this.species = "动物";
    }
    
    //实现继承,使用call apply方法
    function Cat (name,color){
        Animal.call(this,arguments);
        this.name = name;
        this.color = color;
    }
    
    var cat1 = new Cat('大麦','黑色');
    console.log(cat1.species); //动物 -- 这里是通过Call方法继承过来的;

    Ps:通过call方法 改变this指向,从而将Animal的属性继承过来;

    3.第二种方法  prototype模式

     

    function Animal (){
        this.species = "动物";
    }
    function Cat (name,color){this.name = name;
        this.color = color;
    }
    //prototype模式
    Cat.prototype = new Animal();//此处指向变成Animal;
    //将指向重新指向Cat;
    Cat.prototype.constructor = Cat;
    Cat.prototype.run = function (){
        alert(this.name)
    }
    
    var cat1 = new Cat('大麦','黑色');
    console.log(cat1.species);

    Ps:值得注意的是constructor指向,一定让他重新指向自己本身;

    4.第三种  直接原型继承

      第三种方法是对第二种方法的改进。由于Animal对象中,不变的属性都可以直接写入Animal.prototype。所以,我们也可以让Cat()跳过 Animal(),直接继承        Animal.prototype。

    function Cat (name,color){
        this.name = name;
        this.color = color;
    }
    function Animal (){};
        Animal.prototype.species = '动物';
    
        Cat.prototype = Animal.prototype;//缺点是俩个同时指向一个对象,当修改任何一个的时候都会影响另外一个;
    
        //值得注意的是这一块指向,一定让他重新指向自己本身;
        Cat.prototype.constructor = Cat;
    
        var cat1 = new Cat('大毛','黑色');
    
        console.log(cat1.species);//动物

    ps:缺点是俩个同时指向一个对象,当修改任何一个的时候都会影响另外一个;

    5.第四种方法  利用空对象作为媒介

    由于"直接继承prototype"存在上述的缺点,所以就有第四种方法,利用一个空对象作为中介。

    function Animal (){};
    Animal.prototype.species = '动物';
    
    function Cat (name,color){
        this.name = name;
        this.color = color;
    }
    //F是空对象,所以几乎不占内存。这时,修改Cat的prototype对象,就不会影响到Animal的prototype对象。
    
        var F = function (){};
    
        F.prototype = Animal.prototype;
    
        Cat.prototype = new F();
    
        Cat.prototype.constructor = Cat;
    
        var cat1 = new Cat();
        console.log(cat1.species);

    使用的时候我们可以将上面的进行封装;

    //我们将上面的封装成一个函数;
    
    function extend (child,parent){
        var F = function (){};
        F.prototype = parent.prototype;
        child.prototype = new F();
        child.prototype.constructor = child;
    //意思是为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。(uber是一个德语词,意思是"向上"、"上一层"。)这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。
        child.uber = parent.prototype;
    }
    extend(Cat,Animal);
    var cat1 = new Cat();
    console.log(cat1.species);

    6、最后一种方法 拷贝继承

    function Animal (){};
    Animal.prototype.species = '动物';
    
    function Cat (name,color){
        this.name = name;
        this.color = color;
    }
    function extend2 (child,parent){
        var p = parent.prototype;
        var c = child.prototype;
    
            for(var i in p){
            c[i] = p[i]
        }
        c.uber = p;
    }
    
    extend2(Cat,Animal);
    var cat1 = new Cat();
    console.log(cat1.species)//动物    
  • 相关阅读:
  • 原文地址:https://www.cnblogs.com/my-effort/p/5741318.html
  • 最新文章
  • 热门文章
一二三 - 开发者的网上家园