js对象继承

现有一个父类:

function People(name){
  //属性
  this.name  = name
  //实例方法
  this.sleep=function(){
    console.log(this.name + '正在睡觉')
  }
}
//原型方法
People.prototype.eat = function(food){
  console.log(this.name + '正在吃:' + food);
}

我们现在要构造一个子类woman,woman需要拥有people的属性和方法

1.原型链继承

function People(name){
  //属性
  this.name  = name || Annie
  //实例方法
  this.sleep=function(){
    console.log(this.name + '正在睡觉')
  }
}
//原型方法
People.prototype.eat = function(food){
  console.log(this.name + '正在吃:' + food);
}

function Woman(){ 
}
Woman.prototype= new People('haha');
let womanObj = new Woman();
womanObj.sleep()  //haha正在睡觉
womanObj.eat('xiangjiao')  //haha正在吃:xiangjiao

缺点:womanObj中的name是唯一的,因为Woman.prototype= new People('haha'),Woman继承时以及传入了name,因此按需构造多个实例。

2.构造继承

function Woman(name){
 //继承了People
  People.call(this,name);
}
let womanObj = new Woman('haha');
womanObj.sleep() //haha正在睡觉
womanObj.eat('xiangjiao')  // Uncaught TypeError: womanObj.eat is not a function

优点:解决了无法构造多个实例的缺点,同时父类可以有多个,只需要在Women中使用call就可以了,例如增加多一个父类People2.call();

缺点:但同时也带来了问题:无法继承父类中原型链上的方法,例如本例中womanObj中调用eat导致报错。

3.实例继承

function Woman(name){
  let instance = new People();
  instance.name = name
  return instance;
}
let womanObj = new Woman('haha');
console.log(womanObj instanceof People) //true console.log(womanObj instanceof Woman) //false womanObj.sleep() //haha正在睡觉 womanObj.eat('xiangjiao') //haha正在吃:xiangjiao

解决了原型链的继承的问题,但实际上womanObj是people的实例,而不是woman的实例了,有点借壳上市的感觉。

4.组合继承

function Woman(name){
  People.call(this,name)
}
Woman.prototype = People.prototype;
let womanObj = new Woman('haha');
Woman.prototype.constructor = Woman; //为了让constructor从people指向women
console.log(womanObj instanceof Woman) //true console.log(womanObj instanceof People) //true womanObj.sleep() //haha正在睡觉 womanObj.eat('xiangjiao') //haha正在吃:xiangjiao

效果其实和实例继承差不多。缺点是调用了两次父类,同时在Women.prototype上写东西会污染People.prototype

例如:

Woman.prototype.food = 'pingguo'
console.log(People.prototype.food) // pingguo

 想不污染people.prototype其实改动一行就可以了:

Woman.prototype = Object.create(People.prototype)

这其实和下面讲到的寄生组合继承思想是相类似的。

5.寄生式组合继承

function Woman(name){
  //继承父类属性
  People.call(this,name)
}
//继承父类方法
(function(){
  // 创建空类
  let Super = function(){};
  Super.prototype = People.prototype;
  //父类的实例作为子类的原型
  Woman.prototype = new Super();
})();
//修复构造函数指向问题
Woman.prototype.constructor = Woman;
Woman.prototype.food = 'pingguo'
console.log(People.prototype.food)  //undefined
let womanObj = new Woman('haha');
console.log(womanObj instanceof Woman)  //true
console.log(womanObj instanceof People)   //true
womanObj.sleep()  //haha正在睡觉
womanObj.eat('xiangjiao')   //haha正在吃:xiangjiao

所谓寄生,就是把Woman.prototype寄生在了super对象上,这样Women.prototype上的属性和方法就不会污染到People.prototype

6.ES6继承

class People{
  constructor(name='wang'){
    this.name = name;
  }
  eat(){
    console.log(`${this.name} eat food`)
  }
}

class Woman extends People{ 
} 
let womanObj=new Woman('xiaoxiami'); 
womanObj.eat() //xiaoxiami eat food

优点:代码简单,没有原型链等概念,继承效果好。

posted @ 2020-04-14 16:04  想学JS的前端  阅读(105)  评论(0编辑  收藏  举报