JavaScript的继承

这一章节主要说的是类与实例(包括类的声明、生成实例),类与继承(包括如何继承、继承的几种方式)

一、类的声明

 /**
   * 类的声明
   * */
  function Animal (){
    this.name = 'name1'
  }

  /**
   * ES6中class的声明
   * */
  class Animal2 {
    constructor () {
      this.name = 'name2'
    }
  }

二、类的实例化

console.log(new Animal(), new Animal2())

三、类与继承的几种方式(主要是ES5的)

1.继承方案1:将父亲的对象指向孩子

关键代码:Parent1.call(this)

function Parent1(){
  this.name = 'parent1'
  this.play = [1,2,3]
}
function Child1(){
  Parent1.call(this)// 关键代码
  this.type = 'child1'
}
// this指向不同的实例
var s1 = new Child1()
// console.log(s1.play)

缺点:如果父类属性都在父类里则没有问题,如果父类的原型还有方法时,那么子类无法继承父类原型上的方法。

2.继承方案2:借助原型链的方法继承

关键代码:Child2.prototype = new Parent2()

function Parent2(){
  this.name = 'parent2'
  this.play = [1,2,3]
}
function Child2(){
  this.type = 'child2'
}
Child2.prototype = new Parent2()
var s2 = new Child2()
var s3 = new Child2()
s2.play.push(4,5)
console.log(s2.play, s3.play)//[1, 2, 3, 4, 5] (5) [1, 2, 3, 4, 5]这个不是想要看到的

缺点:原型上面的方法时共用的,实例改变值,那么其他的实例也会被改变,这个违背了继承的本质

3.组合继承优化方案一:结合上面1,2

关键代码:Parent3.call(this);Child3.prototype = new Parent3();

function Parent3(){
      this.name = 'paren3'
      this.play = [1,2,3]
    }
    function Child3(){// 这里为第2次
      Parent3.call(this)
      this.type = 'child3'
    }
    Child3.prototype = new Parent3()// 这里1次
    var s4 = new Child3()
    var s5 = new Child3()
    s4.play.push(4,5)
    // console.log(s4.play, s5.play)

缺点:父类的构造函数执行了两次

4.组合继承优化方案二:

关键代码:Child4.prototype = Parent4.prototype

function Parent4(){
  this.name = 'parent4';
  this.play = [1,2,3];
}
function Child4(){
  Parent4.call(this);
  this.type = 'child4'
}
// 这个把Parent4的原型对象上的构造器也继承了
Child4.prototype = Parent4.prototype
// 下面这句是不能写在这里的,因为他们引用的是一个地址
// Child4.prototype.constructor = Child4

var s6 = new Child4();
var sp1 = new Parent4()
console.log(s6 instanceof Child4, s6 instanceof Parent4)
console.log(s6.constructor, sp1.constructor)

缺点:缺点时父类的constructor也被继承了

5.组合继承优化3:采用Object.create()中间件

function Parent5(){
  this.name = 'parent5';
  this.play = [1,2,3];
}
function Child5(){
  Parent5.call(this);
  this.type = 'child5'
}
// 通过Object.create()作为中间物体,将两个构造函数的原型对象上的构造器分开
// 参数是该对象的原型对象,然后把子类的构造函数赋值为该子类
Child5.prototype = Object.create(Parent5.prototype)// 可以通过__proto__去验证
// 如果没有这句话,child5依旧会往上面找到Paren5.prototype
Child5.prototype.constructor = Child5
var s7 = new Child5()
var sp2 = new Parent5()
console.log(s7 instanceof Child5, s7 instanceof Parent5)
console.log(s7.constructor, sp2.constructor)

这种方法还是比较完美的,我们再看下这个原理图,它采用的是Object.create()中间件将两个原型对象分离开。

Child5.prototype.__proto__ === Object.create(Parent5.prototype).__proto__

返回true

 

6.ES6继承方式 

几乎与这种类似,ES6就不在这里说明了,具体看文档,还是比较简单的,文档链接https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/extends。采用extends继承。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值