js面向对象编程之继承

一.子类的原型对象--类式继承

//类式继承
//声明父类
function SuperClass() {
    this.superValue = true;
}
//为父类添加共有方法
SuperClass.prototype.getSuperValue = function() {
     return this.superValue;
};
//声明子类
function SubClass() {
    this.subValue = false;
}

//继承父类
SubClass.prototype = new SuperClass();
//为子类添加共有方法
SubClass.prototype.getSubValue = function() {
    return this.subValue;
};

类式继承就是将子类的原型_ proto_指向父类的原型对象,这个新创建的对象可以访问父类原型上的属性和方法与从父类构造函数中复制的属性和方法。

缺点:

  • 由于子类是通过其原型prototype对父类实例化,如果父类中的共有属性要是引用类型,就会在子类中被所有实例共用,因此一个子类的实例更改子类原型从父类构造函数中继承来的共有属性就会直接影响到其他子类。
  • 由于子类实现的继承是靠其原型prototype对父类的实例化实现的,因此在创建父类的时候,是无法向父类传递参数的,因而在实例化父类的构造函数时也无法对父类构造函数内的属性进行初始化。

二.创建即继承--构造函数继承

//构造函数式继承
//声明父类
function SuperClass(id) {
    //引用类型共有属性
    this.books = [ 'js', 'html', 'css' ];
    //值类型共有属性
    this.id = id;
}
//父类声明原型方法
SuperClass.prototype.showBooks = function() {
    console.log(this.books);
}
//声明子类
function SubClass(id) {
    //继承父类
    SuperClass.call(this, id);
}

SuperClass.call(this, id);这条语句是构造函数式继承的精华,call这个方法可以更改函数的作用环境,这个方法的作用就是将子类的变量在父类中执行一遍,继承父类的共有属性。由于没有涉及原型prototype,子类不继承父类的原型方法。

三.组合继承

//声明父类
function SuperClass(name) {
    //值类型共有属性
    this.name = name;
    // 引用类型共有属性
    this.books = [ 'js', 'html', 'css' ];
}
//父类原型共有方法
SuperClass.prototype.getName = function() {
    console.log(this.name);
};
//声明子类
function SubClass(name, time) {
    //构造函数式继承父类name属性
    SuperClass.call(this,name);
   //子类中新增共有属性
   this.time = time;
}
//类式继承 子类原型继承父类
SubClass.prototype = new SuperClass();
//子类原型方法
SubClass.prototype.getTime = function() {
    console.log(this.time);
};

组合式继承就是在子类构造函数中执行父类构造函数,在子类的原型上实例化父类。

缺点:

在使用构造函数继承时执行了一遍父类的构造函数,而在实现子类原型的类式继承时又调用了一遍父类构造函数,因此父类构造函数调用了两遍。

四.原型式继承

//原型是继承
function inheritObject(o) {
    //声明一个过渡函数对象
    function F() {}
   //过渡对象的原型继承父对象
   F.prototype = o;
   //返回过渡对象的一个实例,该实例的原型继承了父对象
   return new F();
}

原型式继承是对类式继承的一个封装,其中的过渡对象就相当于类式继承中的子类。跟类式继承一样,父类对象中的值类型的属性被复制,引用类型的属性被共用。

五.寄生式继承

//声明基对象
var book = {
      name: "js book",
      alikeBook: [ 'js', 'html', 'css' ]
};
function createBook(obj) {
    //通过原型继承方式创建新对象
    var o = new inheritObject(obj);
   //拓展新对象
   o.getName = function() {
      console.log(name);
   }
   //返回拓展后的新对象
   return o;
}

寄生式继承就是对原型继承的第二次封装,在这个过程中对继承的对象进行了拓展,这样新创建的对象不仅仅有父类中的属性和方法而且还添加新的属性和方法。

六.终极继承者--寄生组合式继承

function inheritObject(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

function inheritPrototype(subClass, superClass) {
  var p = inheritObject(superClass.prototype);
  p.constructor = subClass;
  subClass.prototype = p;
}

function SuperClass(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

SuperClass.prototype.getName = function(){
  console.log(this.name);
};

function SubClass(name, time){
  SuperClass.call(this, name);
  this.time = time;
}

inheritPrototype(SubClass, SuperClass);
SubClass.prototype.getTime = function() {
  console.log(this.time);
};

组合式继承中,通过构造函数继承了父类的属性和方法,并且通过寄生式继承重新继承父类的原型。由于在构造函数中我们已经调用了父类的构造函数,因此我们需要的就是父类原型对象的一个副本。在寄生式继承中要对复制对象p修复其constructor属性指向不正确的问题,最后将得到的复制对象p赋值给子类的原型,这样子类的原型就继承了父类的原型并且没有执行父类的构造函数。

你可能感兴趣的:(js面向对象编程之继承)