简单通俗的方式认识js继承

前戏:

js 继承是在前端面试及js库开发中常常遇到的问题。在面向对象开发时继承知识也是很是重要,本人阅读了一些文章总结了js继承的要点,但愿能对你们有所帮助。前端

什么是继承?

通俗的说:某一个工程须要蓝图实现来工程,蓝图就是。但在一个新工程的蓝图设计时须要复制一些老蓝图上的工程经验来提高效率,这个过程就至关于继承。面试

js继承有哪些? 一块儿来看看

1.类式继承

//父类
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;
}

var instance = new SubClass();

console.log(instance instanceof SuperClass)//true
console.log(instance instanceof SubClass)//true
console.log(SubClass instanceof SuperClass)//false

这种方式是最原始的方式,使用父类的一个实例重写到子类原型对象上,从而实现父类成员的继承,有点继承的样子,可是总以为怪怪的,你肯定把一个实例赋值到原型上真的没有问题吗?数组

缺点:浏览器

  • 引用类型问题,若是父类有个数组成员,只实例化一次赋值到原型上,那就是每次new出来的子实例都是在使用同一个数组,后果可想而知。
  • 不能传参
  • 重写了prototype,若是要额外给子类原型加东西就要加在SubClass.prototype = new SuperClass();重写语句以后,很不方便
  • instance.constructor 构造器指向父类。子类的实例构造器是父类?那不胡扯吗?

2.构造函数继承

function SuperClass(id) {
  this.books = ['a','b'];
  this.id = id;
}
SuperClass.prototype.showBooks = function() {
  console.log(this.books);
}
function SubClass(id) {
  //继承父类
  SuperClass.call(this,id);
}

var instance1 = new SubClass(10);

var instance2 = new SubClass(11);

instance1.books.push('c');
console.log(instance1)
console.log(instance2)
instance1.showBooks();

比上面一个稍微好了一点,也能传参了,每次出来的数组也是惟一的了。原理是在子类构造的时候使用call的特性借用一下父类的构造函数,把父类的成员都设置在子类中来实现继承。额。。那原型呢?
缺点:函数

  • 继承不了父类原型上的成员
  • 每次实例化子类就会call一下父类,多执行了一遍

3.组合式继承

function SuperClass(name) {
  this.name = name; 
  this.books = ['A','B'];
}
SuperClass.prototype.getBooks = function() {
    console.log(this.books);
}
function SubClass(name,time) {
  SuperClass.call(this,name);
  this.time = time;
}
SubClass.prototype = new SuperClass();

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

还能够,能用,原理也就是结合了以上两种(构造函数、类式继承)的继承方式,并修复了严重的缺点。之前应该用这种方法的人也比较多吧
缺点:this

  • call一遍就算了又new了一遍 不以为怪怪的么?call已经设置了一遍成员,prototype只要父的prototype啊,不要把其余无关的东西搞进来。
  • prototype仍是被重写了

4.原型式继承

function inheritObject(o) {
    //声明一个过渡对象
  function F() { }
  //过渡对象的原型继承父对象
  F.prototype = o;
  //返回过渡对象的实例,该对象的原型继承了父对象
  return new F();
}
var book = {
    name:'A book',
    likeBook:['B Book','C book']
}
var newBook = inheritObject(book);
newBook.name = 'AA1 book';
newBook.likeBook.push('CC book');
var otherBook = inheritObject(book);
otherBook.name = 'EE book';
otherBook.likeBook.push('FF book');
console.log(newBook,otherBook);

这就像类式继承同样,直接把父的成员放到子类的原型上,经过原型链来实现继承。inheritObject就像是object.create()和new的模拟实现,产出很是纯净的对象。
黑人问号.jpg。使用这种方法意思是放弃了构造函数来实现继承?
缺点:prototype

  • 子类设置成员写在外面,设置成员的代码一堆一堆的,代码组织差。
  • 每次继承都用同一个likeBook ,并无新建立一个,后果可想而知,那还不是和第一种方法差很少,用不了
  • 这算的上是一种继承么,先拿到父类的东西而后再去想子类?

5.寄生式继承

var book = {
    name:'A book',
    likeBook:['B book','C book']
}
function createBook(obj) {
    //经过原型方式建立新的对象
  var o = new inheritObject(obj);
  // 拓展新对象
  o.getName = function(name) {
    console.log(name)
  }
  // 返回拓展后的新对象
  return o;
}

依然保留了inheritObject函数来实现父成员的继承,相比上面的原型继承代码更有组织性了,单独封装了一个函数来实现继承,而后使用原型继承来继承对应的父类
缺点:
已经差很少作到了继承,可是原型继承问题依然没有解决设计

6.寄生组合式继承

function inheritObject(o) {

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

function inheritPrototype(subClass,superClass) {
    // 复制一份父类的原型副本到变量中
  var p = inheritObject(superClass.prototype);
  // 修正由于重写子类的原型致使子类的constructor属性被修改
  p.constructor = subClass;
  // 设置子类原型
  subClass.prototype = p;
}

//继承
function SuperClass(name) {
  this.name = name;
  this.books=['a book','b book'];
}
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);
}
var instance1 = new SubClass('f1','2017')
var instance2 = new SubClass('r2','2018');

instance1.books.push('new book');

console.log(instance1,instance2);

继承终极版。这个继承方式是在解决组合继承遇到的问题,先给子类链接上纯净的父原型成员,而后再借用父类构造函数获取到父构造函数里的成员,基本解决上面出现的问题。code

总结

剩下没说的就是ES6的继承,也是至关于一个ES6的语法糖,源码也是基于寄生组合式继承。缺点就是对低版本的浏览器不友好, 以上总结了6种js继承方式,每个继承方式都是修复以前继承的不足,重点是理解它们的特色和之间的差别,弄明白为何要这样作,这样才能完全理解js继承的内容。最后,但愿能对你有帮助~对象

相关文章
相关标签/搜索