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

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

内容简介:“继承”是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
复制代码

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

查看所有标签

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

Distributed Systems

Distributed Systems

Sukumar Ghosh / Chapman and Hall/CRC / 2014-7-14 / USD 119.95

Distributed Systems: An Algorithmic Approach, Second Edition provides a balanced and straightforward treatment of the underlying theory and practical applications of distributed computing. As in the p......一起来看看 《Distributed Systems》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具