前端高频面试题——JavaScript中的继承

什么是继承

普通的继承:子女继承父辈的遗产、事业,后人继承祖先的传统、精神
编程语言:继承是面向对象语言的重要特性,继承是针对于类而言,(默认你知道类可以派生实例)子类继承父类,父类中的属性和方法,子类也会包含。见下:

爷爷类 交通工具: 能运输
父类 飞机(继承交通工具) 能运输 能飞 | 父类 汽车(继承交通工具) 能运输 能跑
子类 直升飞机 (继承飞机) 能运输 能飞 直上直下 |
子类 公交车 (继承汽车) 能运输 能跑 收费2元

不难看出继承可以由上自下层层实现,并且子类在保持父类的特性之外,都拥有自己独特的属性。

JavaScript中的继承

JavaScript也属于面向对象语言。与一般的面向对象语言有区别的是,JavaScript中没有类,直接通过函数直接派生实例,详见我的另一篇文章(ES6的class关键字也是通过函数实现 不信你试试 typeof 某class === 'function' / 某class instanceof Function)。
既然面向对象,何不实现继承?
JavaScript的继承方式:通过改变this来实现
(如果没有掌握this和原型链的知识,请参阅我的this以及原型链文章:)

 function Person () {
   this.head = 1;
   this.shoulders = 2; //两个肩膀扛一个脑袋
 }
//将可以复用的方法放入prototype中
Person.prototype.say = function () {
  console.log('hello')
}

实例化:

let oneMan = new Person(); // { head:1, shoulders:2 }
oneMan.say() // hello 

开始继承

子类,定义一个父亲,在函数体内调用Person:

function Father () {
  Person.call(this)
  this.gender = 'male' //性别男
}

调用了Call,Person中的this变成了Father的this,等价于:

function Father () {
   this.head = 1;
   this.shoulders = 2; 
   this.gender = 'male'
}

此时Father也是俩肩膀扛一个脑袋了,并且多了一个性别:

let dad =  new Father() // { head:1, shoulders:2, gender:'male' }

然而现在Father不会说话,因为并没有把Person的说话继承下来

dad.say() // Error dad say is not a function

要想继承prototype,最佳的方式是调用Object.create方法

function __inheritProto ( subClass, superClass ) {
  const subProto = Object.create(superClass.prototype)
  subProto.constructor = subClass //必须将constructor指向直属的构造器
  return subProto
}

完整示例:

 function Person () {
   this.head = 1;
   this.shoulders = 2; //两个肩膀扛一个脑袋
 }
//将可以复用的方法放入prototype中
Person.prototype.say = function () {
  console.log('hello')
}

function Father () {
  Person.call(this)
  this.gender = 'male' //性别男
}

Father.prototype = __inheritProto(Father,Person);

function __inheritProto ( subClass, superClass ) {
  const subProto = Object.create(superClass.prototype)
  subProto.constructor = subClass //必须将constructor指向直属的构造器
  return subProto
}

let dad = new Fataher()
father.head // 1
father.shouders // 2
father.gender // male
father.say() // hello

另一种实践

直接把子类的prototype引向父类

 function Person () {
   this.head = 1;
   this.shoulders = 2; //两个肩膀扛一个脑袋
 }
//将可以复用的方法放入prototype中
Person.prototype.say = function () {
  console.log('hello')
}

// 哪吒,仙人也是人
function Nezha () {
  this.head = 3;
  this.shoulders = 6; //虽然肩膀不算手臂,但不要在意这些细节;
  this.gender = 'male' //性别男
}

Nezha.prototype = new Person()
Nezha.prototype.constructor = Nezha 

let nz = new Nezha()
nz.head // 3 根据就近原则,子类有的属性就不用去__proto__上找了,下同
nz.shouders // 6
nz.gender // male
nz.say() // hello
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 摘要:继承是面向对象思想中的重要概念,虽然严格来说 JavaScript 并属于面向对象类型的语言,但最终还是在E...
    EnochQin阅读 459评论 0 0
  • 基于这篇文章的一些名称约定: 上面的约定应该是比较合理的,如果难以理解,可以查看黯羽轻扬:JS学习笔记2_面向对象...
    一直玩编程阅读 604评论 1 7
  • 很多语言中都有继承的概念,继承这种东西为什么会出现? 简而言之,继承之所以出现,就是为了减少重复无用功。好比爸爸有...
    小丸子啦啦啦呀阅读 424评论 2 0
  • 一、继承的概念 继承是所有面向对象语言中最重要的一个特征。而执行环境也是JS最为重要的一个概念。执行环境定义了变量...
    vinterx阅读 320评论 0 0
  • 不想让很多人看到即使你看到了也不用说话,谢谢。 0121 2018开始似乎就一直“事故不断”让我觉得这个月太漫长了...
    woooooooooood阅读 212评论 0 0

友情链接更多精彩内容