前提

以一个父类为前提条件,列举 js 继承的继承方式:

function Person (age) {this.age = age || 18
}
Person.prototype.sleep = function () {console.log('sleeping')
}
复制代码

:meat_on_bone: 方式 1:原型链继承(不推荐)

function Programmer() {}Programmer.prototype = new Person ()
Programmer.prototype.code = function () {console.log('coding')
}let jon = new Programmer()
jon.code() // coding
jon.sleep() // sleepingjon instanceof Person // true
jon instanceof Programmer // trueObject.getPrototypeOf(jon) // Person {age: 18, code: ƒ}
jon.__proto__ // Person {age: 18, code: ƒ}
复制代码

缺点:

  1. 无法向父类构造函数传参
  2. 父类的所有属性被共享,只要一个实例修改了属性,其他所有的子类实例都会被影响

方式 2:借用构造函数(经典继承)(不推荐)

复制父类构造函数内的属性

function Programmer(name) {Person.call(this)this.name = name
}
let jon = new Programmer('jon')
jon.name // jon
jon.age // 18jon.sleep() // Uncaught TypeError: jon.sleep is not a function
jon instanceof Person // false
jon instanceof Programmer // true
复制代码

优点:

  1. 可以为父类传参
  2. 避免了共享属性

缺点:

  1. 只是子类的实例,不是父类的实例
  2. 方法都在构造函数中定义,每次创建实例都会创建一遍方法

:fried_shrimp: 方式 3:组合继承(推荐)

组合 原型链继承 和 借用构造函数继承 。

function Programmer(age, name) {Person.call(this, age)this.name = name
}Programmer.prototype = new Person()
Programmer.prototype.constructor = Programmer // 修复构造函数指向let jon = new Programmer(18, 'jon')
jon.age // 18
jon.name // jonlet flash = new Programmer(22, 'flash')
flash.age // 22
flash.name // flashjon.age // 18jon instanceof Person // true
jon instanceof Programmer // true
flash instanceof Person // true
flash instanceof Programmer // true
复制代码

优点:融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式

缺点:调用了两次父类构造函数

方式 4:原型式继承(不推荐)

function create(o) {function F() {}F.prototype = oreturn new F()
}let obj = {gift: ['a', 'b']
}let jon = create(obj)
let xiaoming = create(obj)jon.gift.push('c')
xiaoming.gift // ['a', 'b', 'c']
复制代码

缺点:共享了属性和方法

:egg: 方式 5:寄生式继承(不推荐)

创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象

function createObj (o) {var clone = Object.create(o)clone.sayName = function () {console.log('hi')}return clone
}
复制代码

缺点:跟借用构造函数模式一样,每次创建对象都会创建一遍方法

:shaved_ice: 方式 6:寄生组合继承(最佳)

子类构造函数复制父类的自身属性和方法,子类原型只接受父类的原型属性和方法:

function create(prototype) {function Super() {}Super.prototype = prototypereturn new Super()
}function Programmer(age, name) {Person.call(this, age)this.name = name
}Programmer.prototype = create(Person.prototype)
Programmer.prototype.constructor = Programmer // 修复构造函数指向let jon = new Programmer(18, 'jon')
jon.name // jon
复制代码

进阶封装:

function create(prototype) {function Super() {}Super.prototype = prototypereturn new Super()
}function prototype(child, parent) {let prototype = create(parent.prototype)prototype.constructor = child // 修复构造函数指向child.prototype = prototype
}function Person (age) {this.age = age || 18
}
Person.prototype.sleep = function () {console.log('sleeping')
}function Programmer(age, name) {Person.call(this, age)this.name = name
}prototype(Programmer, Person)let jon = new Programmer(18, 'jon')
jon.name // jon
复制代码

引用《JavaScript 高级程序设计》中对寄生组合式继承的夸赞就是:

这种方式的高效率体现它只调用了一次 Parent 构造函数,并且因此避免了在 Parent.prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用 instanceof 和 isPrototypeOf。开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。

:ramen: 方式 7:ES6 extends(最佳)

// 父类
class Person {constructor(age) {this.age = age}sleep () {console.log('sleeping')}
}// 子类
class Programmer extends Person {constructor(age, name) {super(age)this.name = name}code () {console.log('coding')}
}let jon = new Programmer(18, 'jon')
jon.name // jon
jon.age // 18let flash = new Programmer(22, 'flash')
flash.age // 22
flash.name // flashjon instanceof Person // true
jon instanceof Programmer // true
flash instanceof Person // true
flash instanceof Programmer // true
复制代码

优点:不用手动设置原型。

缺点:新语法,只要部分浏览器支持,需要转为 ES5 代码。

:rocket: 参考

  • 《JavaScript 高级程序设计(第 3 版)》6.3 继承
  • 《JavaScript 深入之继承的多种方式和优缺点》 by 冴羽
  • 《ECMAScript 6 入门》Class 的继承 by 阮一峰

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

JS 总结之原型继承的几种方式 1相关推荐

  1. JS 总结之原型继承的几种方式

    在之前的总结中,我们详细分析了原型<JS 总结之原型>,原型很大作用用于模拟继承,这一次,我们来聊原型继承的几种方式. function Person (age) {this.age = ...

  2. js对象:实现继承的几种方式及优缺点

    目录 一.原型链继承 二.构造函数继承 三.组合继承(构造函数式继承+原型链继承) 四.拷贝继承(原型式继承) 五.寄生式继承 六.寄生组合式继承 七.使用ES6中class关键字 一.原型链继承 子 ...

  3. 【JavaScript】js中的原型继承

    文章目录 1. 理解继承 2. js中的继承(原型继承) 3. js6种继承方式 3.1 原型链继承 3.2 盗用构造函数 3.3 组合继承 3.4 原型式继承 3.5 寄生式继承 3.6 寄生式组合 ...

  4. 继承有几种方式,分别是什么,想要实现继承可以使用哪些方法

    这里是修真院前端小课堂,每篇分享文从 [背景介绍][知识剖析][常见问题][解决方案][编码实战][扩展思考][更多讨论][参考文献] 八个方面深度解析前端知识/技能,本篇分享的是: [继承有几种方式 ...

  5. 可以实现继承的几种方式

    继承的几种方式 说起继承,又是一个老生常谈的问题了.今天来讲讲继承的几种方法以及他们的优缺点吧. 源码地址:点击这里 一.原型链继承 原型链继承:通过原型将一个引用类型继承另一个引用类型的属性和方法. ...

  6. Django中Model继承的三种方式

    Django中Model继承的三种方式 Django中Model的继承有三种: 1.抽象继承 2.多表继承 3.proxy model(代理model) 1.抽象继承 第一种抽象继承,创建一个通用父类 ...

  7. js jquery新窗口打开的几种方式

    js jquery新窗口打开的几种方式 第一种:创建一个form表单,通过表单提交来实现新标签页打开. var form = document.createElement('form'); form. ...

  8. js中唤醒弹框的3种方式

    js中唤醒弹框的3种方式 1.alert() 警告框,只有确定按钮,常用于确保用户可以得到某些信息.需点击确定按钮才能继续操作. alert("ss") 2.confirm() 确 ...

  9. (转)js实现继承的5种方式

    js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承有以下通用的几种方式 1.使用对象冒充实现继承(该种实 ...

最新文章

  1. myeclipse 遇到的一些问题及解决方案
  2. CCAH-CCA-500-4题:Where are Hadoop task log files stored?
  3. html 的基本结构、标签(分类、关系)、文档类型、页面语言、字符集、语义化
  4. WorldWind学习系列一:顺利起航篇
  5. 用Java2D画出树的结构图
  6. 【算法数据结构Java实现】时间复杂度为O(n)的最大和序列
  7. Matlab实用程序--图形应用-图形标注
  8. 数据库视频(三)——总结篇
  9. 王之泰201771010131《面向对象程序设计(java)》第九周学习总结
  10. 开源网站云查杀方案,搭建自己的云杀毒。
  11. swagger传递日期类型 json形式
  12. USB On-The-Go引脚
  13. 用计算机里可以加50度电,一台电脑一天用多少度电 节电节能的建议和措施
  14. 七、JVM类加载机制
  15. Leaflet--建设移动设备友好的互动地图
  16. PcShare2007 暗桩
  17. WebSphere安装配置文档
  18. 考拉海购成重构互联网版图的最大“变量”
  19. 硅谷大公司之间的互不挖人协议
  20. 华为吹响“伙伴暨开发者”集结号:共赢数字时代

热门文章

  1. windows 执行CMD命令
  2. android 8 音质,2019安卓公认音质最好手机
  3. 游戏大全(持续更新中……)
  4. SQL语句中的SUBSTR()函数的使用
  5. IB交换机配置命令总结
  6. 将多个npz文件合成成一个由list形式保存的npz文件
  7. IdeaVim 代码补全列表选择快捷键
  8. Linux ARM平台开发系列讲解(TTY) 2.5.2 串口TTY子系统驱动源码分析
  9. 五分钟让你的C语言播放音乐
  10. c语言源代码万年历,万年历-C语言源代码.pdf