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

时间:2021-01-26 19:24:47

    

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

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

 

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)//动物