2.03.07继承

2.03.07 继承

1.简单了解 封装性、继承性、多态性

  • 面向对象有这三个性质:
  1. 封装:把客观存在的数据添加到对象中,即,把构造函数的属性和方法添加到实例对象中
  2. 继承:B对象可以拥有A对象的属性和方法,在js中就叫做B对象继承A对象
  3. 多态:同一构造函数再不同的场景下,可以有不同的表现形式,即,同一构造函数传进的参数不一样,构造出来不同的对象

2.对象之间"继承"的几种方法

1.构造函数绑定

  • 使用call,apply,bind方法,将父对象的构造函数绑定在子对象上
    function Animal(){

        this.species = "动物";

    }

  function Cat(name,color){

        Animal.apply(this);
        Animal.bind(this)();
        //Animal.call(this);
        this.name = name;
        this.color = color;

  }
  
    var cat1 = new Cat("大毛","黄色");
    console.log(cat1.species);  //动物

    // 构造函数原型里方法的继承,需要这样:
    Animal.prototype.say=function(){
        console.log("Woo woo!");
    }
    console.log(cat1);
    // cat1.say();  //控制台报错:Uncaught TypeError: cat1.say is not a function
    console.log(cat1.say);//undefined

    Cat.prototype.say=Animal.prototype.say;
    cat1.say(); //Woo woo!
    console.log(Cat.prototype.say===Animal.prototype.say);//true 
    //证明Cat.prototype.say与Animal.prototype.say指向同一个地址

2.prototype模式

  • 使用prototype属性。如果"猫"的prototype对象,指向一个Animal的实例,那么所有"猫"的实例,就能继承Animal了。
    function Animal(){
        this.species = "动物";
    };

    function Cat(name,color){
    this.name = name;
    this.color = color;
  }

    Cat.prototype = new Animal();
    var cat1 = new Cat("大毛","黄色");
    Cat.prototype.constructor = Cat;
    console.log(cat1.species); // 动物
  • 这种做法必须修改Cat的原型里面的constructor:Cat.prototype.constructor = Cat;这样才不会是的继承连紊乱
  • 若不进行修改,那么实例对象cat1.constructor也指向Animal,这不符合我们的原意,原意是cat1.constructor指向Cat

3.直接继承prototype(不使用)

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

    function Animal(){}
  Animal.prototype.species = "动物";

    function Cat(name,color){
    this.name = name;
    this.color = color;
  }

  Cat.prototype = Animal.prototype;
  Cat.prototype.constructor = Cat;
  var cat1 = new Cat("大毛","黄色");
   console.log(cat1.species); // 动物

  • 与前一种方法相比,这样做的优点是效率比较高(不用执行和建立Animal的实例了),比较省内存。缺点是 Cat.prototype和Animal.prototype现在指向了同一个对象,那么任何对Cat.prototype的修改,都会反映到Animal.prototype。
  • Cat.prototype.constructor = Cat会使得Animal.prototype对象的constructor属性也改掉了!
    console.log(Animal.prototype.constructor); // Cat

4.利用空对象作为中介(修改点3的缺点)

  • 由于"直接继承prototype"存在上述的缺点,所以就有第四种方法,利用一个空对象作为中介。
    function Animal(){
        this.species = "动物";
    };

    function Cat(name,color){
    this.name = name;
    this.color = color;
  }
    
    var F = function(){};
    F.prototype = Animal.prototype;
    Cat.prototype = new F();
    Cat.prototype.constructor = Cat;

    console.log(cat1.species); // 动物
    console.log(F.prototype.constructor);   //Animal
    console.log(Animal.prototype.constructor); // Animal
  • F是空对象,所以几乎不占内存。这时,修改Cat的prototype对象,就不会影响到Animal的prototype对象。
  • 我们将上面的方法,封装成一个函数,便于使用:
    function extend(Child, Parent) {
        var F = function(){};
       F.prototype = Parent.prototype;
       Child.prototype = new F();
       Child.prototype.constructor = Child;
       Child.uber = Parent.prototype;
  }
  • 使用的时候,方法如下:
  extend(Cat,Animal);
  var cat1 = new Cat("大毛","黄色");
  alert(cat1.species); // 动物
  • 这个extend函数,就是YUI库如何实现继承的方法。
  • 另外,说明一点,函数体最后一行:Child.uber = Parent.prototype;
  • 意思是为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。(uber是一个德语词,意思是"向上"、“上一层”。)这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。

5.拷贝继承

  • 我们也可以换一种思路,纯粹采用"拷贝"方法实现继承。简单说,如果把父对象的所有属性和方法,拷贝进子对象,不也能够实现继承吗?这样我们就有了第五种方法。
    function Animal(){
        this.species = "动物";
    }
    Animal.prototype.species = "动物";

    function Cat(name,color){
    this.name = name;
    this.color = color;
  }


    for (var i in Animal.prototype) {
        Cat.prototype[i] = Animal.prototype[i];
    }
    
    var cat1 = new Cat("大毛","黄色");
    console.log(cat1.constructor);  //Cat
    console.log(cat1.species); //动物
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值