对象的继承

238 阅读3分钟

先上图,来了解一下继承关系。

848197-20151205192027502-1027794798.png

原型链继承

面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。

大部分面向对象的编程语言,都是通过“类”(class)实现对象的继承。传统上,JavaScript 语言的继承不通过 class,而是通过“原型对象”(prototype)实现。

通过将自己的原型继承于另外一个构造函数创建出来的对象,将被继承的对象中的所有属性都存在于__proto__属性中.

//父类 
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }

    //子类
    function Star(like) {
      this.like = like;
    }
    //实例化一个Person对象,将对象的地址赋值给Star的prototype属性。
    Star.prototype.name = "郭德纲";
    Star.prototype.age = 48;
    // 【注意】Star.prototype原来指向的对象就没有了,指向新的Person实例对象。
    Star.prototype = new Person("于谦", 52)
    var likes = new Star("抽烟喝酒烫头")
    console.log(likes);

运行结果

1637061572(1).jpg

优点:
父类方法可以复用
缺点:
1.原型链继承多个实例的引用属性指向相同,改变一个会影响另一个实例的属性.如果是引用类型的,继承的是地址,那么子原型中的引用地址和父对象中的引用地址相同
2.不能传递参数, 因为是原型上继承所以不能传递参数
3.继承单一

借用构造函数

在子类构造函数中调用父类构造函数,可以在子类构造函数中使用call()和apply()方法

     function Animals(color, age) {
      this.color = color;
      this.age = age;
      this.eat = "啥都吃";
    }
    function Dog(color, age, name) {
      Animals.call(this, color, age)
      this.name = name;
    }
    var D1 = new Dog("yellow", 1, "小黄");
    var D2 = new Dog("white", 2, "小白");
    console.log(D1);
    console.log(D2);

运行结果

1637062(1).jpg

优点: 可以在子类构造函数中向父类传参数
父类的引用属性不会被共享

缺点: 只能继承父类的实例属性和方法,不能继承到原型中的内容
无法实现构造函数的复用,每个子类都有父类实例函数的副本,影响性能,代码会臃肿

组合继承

组合继承综合了原型链继承和盗用构造函数继承(构造函数继承),将两者的优点结合了起来, 基本的思路就是使用原型链继承原型上的属性和方法,而通过构造函数继承实例属性,这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。

function Animals(color, age,) {
      this.color = color;
      this.age = age;
      this.bodyType = ["Fat"];
    }
    // 将父类的方法定义在父类的原型对象上。
    Animals.prototype.eat = function () {
      console.log("啥都吃");
    }

    function Dog(color, age, name) {
      //在子类的构造函数中借用父类的构造函数
      Animals.call(this, color, age)
      this.name = name;
    }
    //将子类的原型对象指向 父类的实例对象
    Dog.prototype = new Animals();
    var D1 = new Dog("yellow", 1, "小黄");

    //修正 Dog的原型对象上 constructor属性 的指向。
    Dog.prototype.constructor = Animals;
    D1.eat();
    D1.bodyType.push("tall");
    var D2 = new Dog("white", 2, "小白");
    console.log();
    console.log(D1);
    console.log(D2);

运行结果:

11(1).jpg

优点: 父类的方法可以复用
可以在子类构造函数中向父类构造函数中传参
父类构造函数中的引用属性不会被共享