史上最为详细的javascript继承(推荐)


Posted in Javascript onMay 18, 2019

前言

为大家分享js中最常见最详细的继承方式,接下来将一下面的几个维度进行展示说明
文章有点长,请耐心阅读?,有什么错误理解的地方希望留言指出来

  1. 产生原因
  2. 代码实现
  3. 基本原理
  4. 语言实现
  5. 场景优点
  6. 缺点

继承方式

  1. 原型链继承
  2. 借用构造函数模式继承
  3. 组合继承
  4. 原型式继承
  5. 寄生式继承
  6. 寄生组合

原型链继承
相信小伙伴们都知道到原型链继承(ECMAScript 中描述了原型链的概念,并将原型链作为实现继承的主要方法),因为原型链继承非常的强大,但是也有它的缺点,接下来咱们就按照上面的维度看看原型链继承到底是什么鬼
代码实现:(需要两个构造函数来完成一个原型链继承)

// SuperType 构造函数称为超类
 function SuperType (){
   this.name='super';
   this.friend=[];
   this.property = true; 
}
SuperType.prototype.getName=function(){
  return this.name;
}
SuperType.prototype.getSuperValue = function(){
 return this.property;
}; 
// SubType 构造函数称为子类
function SubType(name,age){
  this.name=name;
  this.age=age;
  this.subproperty = false; 
}
SubType.prototype=new SuperType();
SubType.prototype.constrcutor=SubType;
SubType.prototype.getAge=function(){
  return this.age;
}
SubType.prototype.getSubValue = function (){
 return this.subproperty;
}; 
var child = new SubType('shiny',12);
console.log(child.getName)//shiny
console.log(child.getAge())//12

图解部分 属性

史上最为详细的javascript继承(推荐)

基本原理

使用类似作用域的原型链,进行继承查找

语言实现

定义两个构造函数,分别为父类(SuperType)、子类(SubType),为了实现子类能够使用父类的属性(本身和原型上面的属性)。重写子类的原型,让子类的原型指向父类实例,这样子类的构造函数就是父类的实例地址,实现子类可以使用父类的本身和原型上的属性

优点

子类可以通过原型链的查找,实现父类的属性公用与子类的实例

缺点  

  1. 一些引用数据操作的时候会出问题,两个实例会公用继承实例的引用数据类
  2. 谨慎定义方法,以免定义方法也继承对象原型的方法重名
  3. 无法直接给父级构造函数使用参数

借用构造函数模式继承
虽然原型链继承很强大但是也有他的缺点,借用构造函数继承可以解决原型链继承的缺点,开线面的解释
代码实现:

// 把父类当中一个函数使用
function SuperType(name){
this.name=name
this.friend=['a','b']
}
SuperType.prototype.getFriend=function(){
 return this.firend
}
function SubType(name){
 // 执行父类函数
 SuperType.call(this,name);
}
var child = new SubType('shiny')
var childRed = new SubType('red')
console.log(child.name)//shiny
console.log(childRed.name)//red
child.firend.push('c')
console.log(child.friend)//a,b,c
console.log(childRed.friend)//a,b
console.log(childRed.getFriend)//undefined

基本原理

使用call apply方法,通过执行方法修改tihs (上下文),是的父级的this变成子类实例的this,这样每个实例都会得到父类的属性,实现引用属性备份

使用场景

父类中需要一些子类使用共享的引用类型,并且子类可能会操作父类共享的引用类型
但是父类的非this绑定的属性和方法是不可以使用的(放在父类prototype的属性和方法)

语言实现

不要把父类当中构造函数,当中一个函数来处理这样更容易理解,在子类的构造函数中借用父类函数通过修改this来执行,这样子类的实例包含父类的属性

优点

  1. 解决了原型链继承的 引用类型操作问题
  2. 解决了父类传递参数问题

缺点

  1. 仅仅使用借用构造函数模式继承,无法摆脱够着函数。方法在构造函数中定义复用不可谈
  2. 对于超类的原型定义的方法对于子类是不可使用的,子类的实例只是得到了父类的this绑定的属性
  3. 考虑到这些缺点,单独使用借用构造函数也是很少使用的

组合继承

上面的两种继承方式(原型链继承+借用构造函数继承),都有自己优缺点,但是他们不是很完美,下面解释一下组合继承

代码实现:

 

function SuperType(name){
  this.name=name;
  this.firend=['a','b']
}
SuperType.prototype.getName=function(){
  return this.name
}
function SubType(name,age){
  this.age=age;
  SuperType.call(this,name)
}
SubType.prototype=new SuperType();
SubType.prototype.constrcutor = SubType;
SubType.prototype.getAge=function(){
  return this.age
}
var childShiny=new SubType('shiny',23);
var childRed = new SubType('red',22);
childShiny.firend.push('c');
childRed.firend.push('d');
console.log(childShiny.getName());
console.log(childShiny.getAge());
console.log(childRed.getName());
console.log(childRed.getAge());
console.log(childRed.friend);//[a,b,d]
console.log(childShiny.friend);//[a,b,c]

 基本原理

使用原型链的继承实现,通过原型查找功能来满足原型链共享方法
使用借用构造函数方法,使用实例备份父类共享引用类型备份

使用场景

得到原型链继承和构造函数继承的优点,是被开发人员认可的一种继承方式,但是也有他的缺点
语言实现

定义两个构造函数,分别为父类(SuperType)、子类(SubType),为了实现子类能够使用父类的属性(本身和原型上面的属性)。重写子类的原型,让子类的原型指向父类实例,这样子类的构造函数就是父类的实例地址,实现子类可以使用父类的本身和原型上的属性
不要把父类当中构造函数,当中一个函数来处理这样更容易理解,在子类的构造函数中借用父类函数通过修改this来执行,这样子类的实例包含父类的属性

优点

  1. 解决了原型链继承引用类型的实例操作导致引用改变
  2. 解决了借构造函数继承方式的,父类原型子类实例可以使用

缺点

  1. 父类的构造函数被实例换了两次
  2. 实例会有父类的构造函数的一些this属性、子类的构造函数(prototype)上也有一份实例的上有的属性

原型式继承

话说上面的的组合继承不是已经被开发者认可了吗,原型式继承是啥?下面咱们看看原型式继承是什么样的。

代码实现:

1 function object(o){
 function F(){};
 F.prototype=o;
  return new F()
}
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var personShiny = object(person);
var personRed = object(person);
console.log(personShiny.name)//Nicholas
console.log(personRed.name)//Nicholas
personShiny.friends.push('red');
personRed.friends.push('shiny');
console.log(personShiny.friends)//["Shelby", "Court", "Van","red","shiny"]
//ECMAScript 5 通过新增 Object.create()方法规范化了原型式继承。这个方法接收两个参数:一
//个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的情况下,
//Object.create()与 object()方法的行为相同。
2 
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var personShiny = Object.create(person);
var personRed = Object.create(person);
console.log(personShiny.name)//Nicholas
console.log(personRed.name)//Nicholas
personShiny.friends.push('red');
personRed.friends.push('shiny');
console.log(personShiny.friends)//["Shelby", "Court", "Van","red","shiny"]

基本原理

通过Object.create()方法来创建一个有基础类的实例,这实例的__proto__指向基础类

使用场景

在不使用构造函数的情况下,只想让一个对象与另一个对象保持类似的情况下

语言实现

需要创建一个基础对象,作为一个新对象的基础对象,通过object方法或者Object.create方法处理得到一个新实例,这个新实例上的__proto__指向基础对象

优点

再不用创建构造函数的情况下,实现了原型链继承,代码量减少一部分

缺点

  1. 一些引用数据操作的时候会出问题,两个实例会公用继承实例的引用数据类
  2. 谨慎定义方法,以免定义方法也继承对象原型的方法重名
  3. 无法直接给父级构造函数使用参数

寄生继承

咱们看了上面的原型式继承,其实就是和原型链继承差别不大,只是省去了构造函数这一部,但是原型式继承也是有缺点的(不能够给备份的对象添加属性),下面寄生继承来解决。

代码实现:

// 和工厂模式非常类似,创建一个对象,增强一些功能并返回该对象
function createAnother(o){
  var clone = Object(o);
  clone.sayHi=function(){
   console.log('hi')
}
  return clone
}
var person = {
  name:'shiny',
  friends:['a','b']
}
var personShiny = createAnother(person);
console.log(personShiny.sayHi())//Ho

基本原理

备份一个对象,然后给备份的对象进行属性添加,并返回

使用场景

在考不使用构造函数的情况下实现继承,前面示
范继承模式时使用的 object()函数不是必需的;任何能够返回新对象的函数都适用于此模式

语言实现

类似构造函数,通过一个执行方法,里面创建一个对象,为该对象添加属性和方法,然后返回

优点

  1. 再不用创建构造函数的情况下,实现了原型链继承,代码量减少一部分
  2. 可以给备份的对象添加一些属性

缺点

类似构造函数一样,创建寄生的方法需要在clone对象上面添加一些想要的属性,这些属性是放在clone上面的一些私有的属性

寄生组合继承

咱们看了上面的组合继承看上去已经很完美了,但是也有缺点(父类被实例化两次、子类实例和子类的构造函数都有相同的属性),寄生组合就是来解决这些问题的

代码实现:

function inheritPrototype({SubType,SuperType}){
   const prototype = Object(SuperType.prototype);
   prototype.constrcutor=SubType;
   SubType.prototype=prototype;
}
function SuperType(name){
  this.name=name;
  this.friends=['a','b']
}
SuperType.prototype.getName=function(){
  return this.name;
}
function SubType(name,age){
  this.age=age;
  SuperType.call(this,name)
}
inheritPrototype({SubType,SuperType});
SubType.prototype.getAge=function(){
  return this.age
}
var SubTypeShiny = new SubType('Shiny',23);
SubTypeShiny .friends.push('c')
var SubTypeRed = new SubType('Red',21);
SubTypeRed .friends.push('d')
console.log(SubTypeShiny.getName())//Shiny
console.log(SubTypeShiny.getAge())//22
console.log(SubTypeShiny.friends)//['a','b','c']
console.log( SubTypeRed.getName())//Red
console.log( SubTypeRed.getAge())//21
console.log( SubTypeRed.friends)//['a','b','d']

基本原理

子类构造函数内通过call、apply方法进行修改父类构造函数的this和执行父类构造函数,使的子类的实例拥有父类构造函数的一些属性,
结合子类的原型修改成父类构造函数的原型,并把父类的原型的constructor指向子类构造函数

使用场景

在考不使用构造函数的情况下实现继承,前面示

范继承模式时使用的 object()函数不是必需的;任何能够返回新对象的函数都适用于此模式

语言实现

极度类似组合寄生方式,只是修改了子类原型链继承的方式,组合寄生是继承父类的实例,寄生组合寄生则是通过一子类的原型继承父类的原型,并把该原型的constructor指向子类构造函数

优点

  1. 在少一次实例化父类的情况下,实现了原型链继承和借用构造函数
  2. 减少了原型链查找的次数(子类直接继承超类的prototype,而不是父类的实例)

缺点

暂无

下面是组合继承和寄生组合继承的原型图对比

史上最为详细的javascript继承(推荐)

以上所述是小编给大家介绍的javascript继承详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
用 JSON 处理缓存
Apr 27 Javascript
响应鼠标变换表格背景或者颜色的代码
Mar 30 Javascript
checkbox全选/取消全选以及checkbox遍历jQuery实现代码
Dec 02 Javascript
用js判断页面刷新或关闭的方法(onbeforeunload与onunload事件)
Jun 22 Javascript
js实现简单锁屏功能实例
May 27 Javascript
Bootstrap每天必学之滚动监听
Mar 16 Javascript
jquery实现简单的banner轮播效果【实例】
Mar 30 Javascript
js仿3366小游戏选字游戏
Apr 14 Javascript
JS打印组合功能
Aug 04 Javascript
js实现京东轮播图效果
Jun 30 Javascript
微信小程序实现点击图片放大预览
Oct 21 Javascript
解决vue2中使用elementUi打包报错的问题
Sep 22 Javascript
微信小程序云开发如何使用npm安装依赖
May 18 #Javascript
vue路由中前进后退的一些事儿
May 18 #Javascript
如何写好一个vue组件,老夫的一年经验全在这了(推荐)
May 18 #Javascript
微信小程序云开发 生成带参小程序码流程
May 18 #Javascript
详解小程序开发经验:多页面数据同步
May 18 #Javascript
JavaScript实现星级评价效果
May 17 #Javascript
JavaScript实现美化滑块效果
May 17 #Javascript
You might like
让PHP更快的提供文件下载的代码
2012/06/13 PHP
Symfony2实现在doctrine中内置数据的方法
2016/02/05 PHP
PHP多维数组指定多字段排序的示例代码
2018/05/16 PHP
一个判断email合法性的函数[非正则]
2008/12/09 Javascript
jquery JSON的解析方式
2009/07/25 Javascript
封装的jquery翻页滚动(示例代码)
2013/11/18 Javascript
JS生成某个范围的随机数【四种情况详解】
2016/04/20 Javascript
全面解析JS字符串和正则表达式中的match、replace、exec等函数
2016/07/01 Javascript
jQuery layui常用方法介绍
2016/07/25 Javascript
同步文本框内容JS代码实现
2016/08/04 Javascript
微信小程序实现锚点定位楼层跳跃的实例
2017/05/18 Javascript
AngularJS实用基础知识_入门必备篇(推荐)
2017/07/10 Javascript
一个Js文件函数中调用另一个Js文件函数的方法演示
2017/08/14 Javascript
如何选择适合你的JavaScript框架
2017/11/20 Javascript
vue-cli webpack模板项目搭建及打包时路径问题的解决方法
2018/02/26 Javascript
Express之托管静态文件的方法
2018/06/01 Javascript
Vue子组件向父组件通信与父组件调用子组件中的方法
2018/06/22 Javascript
vue组件之间通信方式实例总结【8种方式】
2019/02/22 Javascript
[01:04]DOTA2:伟大的Roshan雕塑震撼来临
2015/01/30 DOTA
[01:05:52]DOTA2-DPC中国联赛 正赛 Ehome vs Aster BO3 第一场 2月2日
2021/03/11 DOTA
windows10系统中安装python3.x+scrapy教程
2016/11/08 Python
Python数据操作方法封装类实例
2017/06/23 Python
PyQt5每天必学之布局管理
2018/04/19 Python
Python3 venv搭建轻量级虚拟环境的步骤(图文)
2019/08/09 Python
解决pyCharm中 module 调用失败的问题
2020/02/12 Python
python GUI库图形界面开发之PyQt5图片显示控件QPixmap详细使用方法与实例
2020/02/27 Python
python 实现批量图片识别并翻译
2020/11/02 Python
浅谈html5之sse服务器发送事件EventSource介绍
2017/08/28 HTML / CSS
局域网标准
2016/09/10 面试题
最新党员的自我评价分享
2013/11/04 职场文书
营销专业应届生求职信
2013/11/26 职场文书
公司业务主管岗位职责
2013/12/07 职场文书
六查六看剖析材料
2014/02/15 职场文书
2015毕业寄语大全
2015/02/26 职场文书
2015年仓库管理工作总结
2015/05/25 职场文书
使用pd.merge表连接出现多余行的问题解决
2022/06/16 Python