继承的这6种方式!(上)

栏目: JavaScript · 发布时间: 5年前

内容简介:“继承”是JavaScript面向对象设计的重要一环,愿你认真读完本文,吃透继承的概念。在js中,继承主要是依靠原型链是实现继承最原始的模式,即通过prototype属性实现继承。

  “继承”是JavaScript面向对象设计的重要一环,愿你认真读完本文,吃透继承的概念。

继承的核心

  在js中,继承主要是依靠 原型链 实现的,原型链是通往继承的必经之路。你可以参考 《一张图彻底KO原型链(prototype,__proto__)》 这篇博文,相信它一定能很好地帮助你原型链。

1. 继承方式一:原型链

1.1 介绍

  原型链是实现继承最原始的模式,即通过prototype属性实现继承。

//父级-构造函数
function Father() {
  this.fatherProp = true
}

//父级-原型属性
Father.prototype.getFatherValue = function() {
  return this.fatherProp
}

//子级-构造函数
function Son() {
  this.sonProp = false
}

//子级-原型属性:继承父级
//即__proto__指向父级的prototype
//若不理解请阅读《一张图彻底KO原型链(prototype,__proto__》
Son.prototype = new Father()

//子级-添加原型方法
Son.prototype.getSonValue = function() {
  return this.sonProp
}

//创建子级的实例对象
var son = new Son()
console.log(son.getFatherValue()) //true
复制代码

1.2 解析:son实例对象是如何找到getFatherValue()方法的呢?

  1. 首先在son对象自身中找。若对象自身没找到
  2. 然后在Son.prototype中找。若Son.prototype中没找到
  3. 继续往上一层,Son.prototype.__proto__(Fater.prototype)
  4. 依次类推,直到找到需要的属性或方法,或到达原型链顶端Object.prototype

  如果到最后都没找到,会发生什么呢?

//一个不存在的方法
console.log(son.getValue()) //ERROE:not a function
复制代码

1.3 注意事项

  1. 重写父级原型链的方法或者添加父级原型链不存在的方法,必须在父级原型链代码之后。(这个很好理解,不放代码演示了)

  2. 通过原型链实现继承后,不能再使用字面量的方式创建原型对象,因为会覆盖原型链。

//子级-原型属性:继承父级
Son.prototype = new Father()

//不能像下面这样,这样会使得上面的代码无效
//因为这相当于重新创建了一个原型对象
Son.prototype = {
  getSonValue: function() {
    return this.sonProp
  }
}
复制代码

1.4 原型链实现继承的弊端

   世间万事万物都不可能十全而十美,原型链虽然强大,但也存在缺陷。

  1. 原型链中引用类型的属性会被所有实例共享的,即所有实例对象使用的是同一份数据,会相互影响。
function Father() {
    this.arr = [1,2,3]
  }

  function Son() {
  }

  Son.prototype = new Father()

  var son1 = new Son()
  console.log(son1.arr)  //1,2,3

  var son2 = new Son()
  son2.arr.push(4)

  console.log(son2.arr)  //1,2,3,4
  console.log(son1.arr)  //1,2,3,4
复制代码
  1. 无法向父级构造函数传参

2. 继承方式二:借用构造函数

2.1 介绍

  方式一中引用类型带来的问题可借用构造函数的方式解决。其核心思想是:在子级构造函数中调用父级构造函数。

  如何实现在一个构造函数中调用另一个函数?——call()和apply()

function Father() {
    this.arr = [1,2,3]
  }

  function Son() {
    //call的第一个函数是this指向的对象,即构造函数的实例对象
    Father.call(this)

    /*上面代码等同于下面这段代码:
    (function() {
      this.arr = [1,2,3]
    }).call(this)
    */
  }

  var son1 = new Son()
  console.log(son1.arr)  //1,2,3

  var son2 = new Son()
  son2.arr.push(4)

  console.log(son2.arr)  //1,2,3,4
  console.log(son1.arr)  //1,2,3
复制代码
//解决传参问题:
function Father(name) {
  this.name = name
}

function Son(name) {
  Father.call(this, name)
}

var son1 = new Son("小名")
console.log(son1.name)    //小名

var son2 = new Son("一灯")
console.log(son2.name)    //一灯
复制代码

2.2 借用构造函数的缺陷

  这种方式是通过构造函数实现的,当然也把构造函数自身的问题带过来了—— 破坏了复用性 。因为每个实例都创建了一份副本。

3. 组合继承

3.1 介绍

  组合继承 = 原型链 + 借用构造函数。取其长避其短:共享的用原型链,各自的借用构造函数

function Father(name) {
  this.name = name
  this.arr = [1,2,3]
}

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

function Son(name, age) {
  Father.call(this, name)
  this.age = age
}

Son.prototype = new Father()
Son.prototype.constructor = Son
Son.prototype.getAge = function() {
  console.log(this.age)
}

var son1 = new Son("小名", 23)
son1.arr.push(4)
console.log(son1.arr) //1,2,3,4
son1.getName()        //小名
son1.getAge()         //23

var son2 = new Son("一灯", 24)
console.log(son2.arr) //1,2,3
son1.getName()        //一灯
son1.getAge()         //24
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序设计抽象思想

程序设计抽象思想

Eric S.Roberts、闪四清 / 闪四清 / 清华大学出版社 / 2005-6 / 78.00元

本书全面介绍了数据结构的基础内容。介绍了多个库包,可用于简化编程流程;详细讨论了递归编程的用法,包括大量难度各异的编程示例和练习。一起来看看 《程序设计抽象思想》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具