JavaScript中的继承

JavaScript中的继承有多种实现,我们一步步来,层层深入下。

一、 原型继承,又称类式继承。

  实现:将父类的示例赋值给子类的原型对象prototype。

  代码示例: 

function SuperType() {
    this.prop = 'super';
};

SuperType.prototype.getName = function () {
    console.log(this.prop);
};

function SubType() {
    this.subProp = 'sub';
};

SubType.prototype = new SuperType(); // 原型继承的精华

var sub = new SubType();
sub.getName(); // super
console.log(sub.subProp) // sub

  解释:将父类的示例赋值给子类的原型对象prototype,则子类的原型对象不仅会拥有父类构造函数中的所有属性和方法,还会拥有父类原型对象中的属性和方法。

  因此在实例化子类对象时,子类不仅会执行子类的构造函数,拥有子类构造函数中的属性和方法,还会继承来自子类原型上的属性和方法,

  而子类原型上的属性和方法已通过 SubType.prototype = new SuperType() 拥有了父类构造函数和父类原型上的属性和方法,

  从而子类也拥有了父类构造函数和父类原型上的属性和方法。。。

 

  缺点:

    1. 如果父类中的共有属性是引用类型,就会在子类实例中被所有实例公用。

    2. 由于子类实现的继承是靠其原型对父类实例化实现的,因此在创建父类的时候是无法像父类传参的。  

function SuperType() {
    this.arr = ['aa', 'bb'];
};

function SubType() {};

SubType.prototype = new SuperType();

var sub1 = new SubType();
var sub2 = new SubType();
sub1.arr.push('cc');

console.log(sub1.arr); // ["aa", "bb", "cc"]
console.log(sub2.arr); // ["aa", "bb", "cc"]

 

二、构造函数继承

  实现:在子类构造函数中执行一遍父类的构造函数。

  代码实例:

function SuperType(prop) {
    this.superProp = prop;
    this.arr = ['aa', 'bb'];
};

SuperType.prototype.getArr = function () {
    console.log(this.arr);
};

function SubType(prop) {
    SuperType.call(this, prop); // 可以传参
};

var sub1 = new SubType('super1');
var sub2 = new SubType('super2');
sub1.arr.push('cc');

console.log(sub1.superProp) // super1
console.log(sub2.superProp) // super2

console.log(sub1.arr); // ["aa", "bb", "cc"]
console.log(sub2.arr); // ["aa", "bb"]  arr没有被实例共用

console.log(sub1.getArr) // undefined  原型上的属性或方法无法继承

  虽然这种方式解决了原型继承出现的问题,但这种方式也是有明显的缺点的。

  缺点:由于实现继承没有涉及到原型prototype,所以父类的原型方法自然不会被子类继承。而如果想要实现继承,则必须将方法放在构造函数中,

     但这样创建出来的每个实例都会单独拥有一份而不会共用,就会违背代码复用的原则。

三、混合继承

  实现:将上述两种方式混合使用,解决上述两种方式出现的问题。

  代码示例:

function SuperType(prop) {
    this.superProp = prop;
    this.arr = ['aa', 'bb'];
};

SuperType.prototype.getArr = function () {
    console.log(this.arr);
};

function SubType(prop) {
    SuperType.call(this, prop);
};

SubType.prototype = new SuperType();

var sub1 = new SubType('super1');
var sub2 = new SubType('super2');
sub1.arr.push('cc');

console.log(sub1.superProp) // super1
console.log(sub2.superProp) // super2

sub1.getArr() // ["aa", "bb", "cc"]
sub2.getArr() // ["aa", "bb"]

  同样,这种继承方式也是有缺点的,由于在使用构造函数继承时我们执行了一遍父类的构造函数,在原型继承的时候我们又执行了一遍父类的构造函数,

  这样就使得父类的构造函数被执行了两遍。看来这也不是最完美的实现继承的方式。

  那么,到底存不存在最完美的实现继承的方式呢?

  后面会继续补充~~

posted @ 2017-02-20 12:31  小四张  阅读(195)  评论(0编辑  收藏  举报