JavaScript寄生组合式继承实例详解


Posted in Javascript onJanuary 06, 2018

本文实例讲述了JavaScript寄生组合式继承。分享给大家供大家参考,具体如下:

其实《JavaScript高级程序设计》这本书中已经有完整代码了,只要把代码读懂就知道这个继承是怎么回事。

首先,在js中,给对象定义属性有两种方式:

//通过执行构造函数设置属性
function A(){
  this.a = 1;
}
//通过原型设置属性
A.prototype.b = 1;

所以:

一个类Sub要继承另一个类Super,需要继承父类的prototype下的属性,还要执行一下父类的构造函数。

一个类Sub要继承另一个类Super,既要通过原型链实现对原型属性和方法的继承,又要通过在子类构造函数内调用父类构造函数实现对实例属性的继承

1. 继承prototype下的属性

上面可以看到,Super类的prototype下的属性是没有被继承的,因此下面还需要继承这一部分。

直接「=」肯定不行,因为Sub.prototype中修改属性后,不能影响Super.prototype里面的对象,即不能Sub.prototype=Super.prototype

首先写一个创建对象副本的方法

function object(o){
  function A(){}
  A.prototype = o
  var ox = new A()
  return ox
}

上面的函数得到的对象ox,拥有了对象o的全部属性(在原型链上),而修改ox的属性,不会影响到o,相当于把o复制了一份。

原型式继承就是上面的“object”函数,在很多类库源码中都能发现它的身影

简单而言,原型式继承就是不用实例化父类了,直接实例化一个临时副本实现了相同的原型链继承。(即子类的原型指向父类副本的实例从而实现原型共享)

tips:总所周知,原型链继承是子类的原型指向父类的实例从而实现原型共享,而原型式继承是子类的原型指向父类副本的实例从而实现原型共享

ECMAScirpt 5通过新增Object.create()方法规范化了原型式继承。

使用object方法,就可以将Super.prototype的属性「复制」到Sub.prototype上了,当然这儿还需要修正一下constructor的指向。

function inherit(subType,superType){
 var prototype=Object.create(superType.prototype);
 prototype.constructor=subType;
 subType.prototype=prototype;
}

2. 分别执行父类和子类的构造函数,继承这部分下的属性:

//父类
function Super(){
this.sss=1
}
//子类
function Sub(){
//arguments是Sub收到的参数,将这个参数传给Super
Super.apply(this, arguments)
}
//实例
sub = new Sub()

Super.apply(this, arguments)这一句,将Super类作为一个普通函数来执行,但是Super类的this被换成了Sub类的this,Sub收到的参数也传给了Super

最后执行结果相当于sub.sss=1

附上各种继承方式的特点和优缺点

曾经一段时间因为javascript关于类实现继承的不规范,导致各种各样实现继承的代码;而实际上不管代码怎么变,继承都基于两种方式:

1.通过原型链,即子类的原型指向父类的实例从而实现原型共享。
2.借用构造函数,即通过js的apply、call实现子类调用父类的属性、方法;

原型链方式可以实现所有属性方法共享,但无法做到属性、方法独享(例如Sub1修改了父类的函数,其他所有的子类Sub2、Sub3...想调用旧的函数就无法实现了);

借用构造函数除了能独享属性、方法外还能在子类构造函数中传递参数,但代码无法复用。总体而言就是可以实现所有属性方法独享,但无法做到属性、方法共享(例如,Sub1新增了一个函数,然后想让Sub2、Sub3...都可以用的话就无法实现了,只能Sub2、Sub3...各自在构造函数中新增)。

组合继承就是把以上两种继承方式一起使用,把共享的属性、方法用原型链继承实现,独享的属性、方法用借用构造函数实现,所以组合继承几乎完美实现了js的继承;为什么说是“几乎”?因为认(dan)真(teng)的geek们发现组合继承有一个小bug,实现的时候调用了两次超类(父类),性能上不合格啊有木有!怎么解决呢?于是“寄生继承”就出来了。

寄生继承(原型式继承)就是不用实例化父类了,直接实例化一个临时副本实现了相同的原型链继承。(即子类的原型指向父类副本的实例从而实现原型共享)

“寄生组合继承”用了“寄生继承”修复了“组合继承”的小bug,从而让js完美实现继承了。

实例代码:

function SuperType(name,colors){
  this.name=name;
  this.colors=colors;
}
SuperType.prototype.getSuperProperty=function(){ return this.name; }
function SubType(job,name,colors){
  SuperType.call(this,name,colors);
  this.job=job;
}
SubType.prototype.getSubPrototype=function(){ return this.job; }
function inherit(subType,superType){
  var prototype=Object.create(superType.prototype);
  prototype.constructor=subType;
  subType.prototype=prototype;
}
inherit(SubType,SuperType);
var instance=new SubType("doctor","John",["red","green"]);
console.log(instance.getSubPrototype());  //输出"doctor"
console.log(instance.getSuperProperty());  //输出"John",成功调用在父类原型定义的方法

属性继承代码是SuperType.call(this,name,colors);

原型继承代码是inherit(SubType,SuperType);

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
jQuery对象和DOM对象相互转化
Apr 24 Javascript
checkbox设置复选框的只读效果不让用户勾选
Aug 12 Javascript
jQuery操作元素css样式的三种方法
Jun 04 Javascript
javascript操作数组详解
Dec 17 Javascript
为JS扩展Array.prototype.indexOf引发的问题及解决办法
Jan 21 Javascript
轻松学习jQuery插件EasyUI EasyUI实现拖放商品放置购物车
Nov 30 Javascript
BootStrap栅格系统、表单样式与按钮样式源码解析
Jan 20 Javascript
React Native仿美团下拉菜单的实例代码
Aug 08 Javascript
React中使用UEditor百度富文本的方法
Aug 22 Javascript
Javascript 类型转换、封闭函数及常见内置对象操作示例
Nov 15 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
May 08 Javascript
jQuery实现滑动开关效果
Aug 02 jQuery
基于jquery trigger函数无法触发a标签的两种解决方法
Jan 06 #jQuery
JS实现非首屏图片延迟加载的示例
Jan 06 #Javascript
jQuery中库的引用方法
Jan 06 #jQuery
基于JavaScript中标识符的命名规则介绍
Jan 06 #Javascript
js生成word中图片处理方法
Jan 06 #Javascript
详解webpack中的hash、chunkhash、contenthash区别
Jan 05 #Javascript
浅谈webpack对样式的处理
Jan 05 #Javascript
You might like
解析CodeIgniter自定义配置文件
2013/06/18 PHP
PHP脚本监控Nginx 502错误并自动重启php-fpm
2015/05/13 PHP
CodeIgniter读写分离实现方法详解
2016/01/20 PHP
php基于PDO连接MSSQL示例DEMO
2016/07/13 PHP
PHP目录与文件操作技巧总结(创建,删除,遍历,读写,修改等)
2016/09/11 PHP
PHP给前端返回一个JSON对象的实例讲解
2018/05/31 PHP
jQuery之浮动窗口实现代码(两种方法)
2010/09/08 Javascript
提取字符串中年月日的函数代码
2013/11/05 Javascript
JavaScript程序中的流程控制语句用法总结
2016/05/23 Javascript
深入浅析JavaScript函数前面的加号和叹号
2016/07/09 Javascript
NodeJS仿WebApi路由示例
2017/02/28 NodeJs
详解Vue.js之视图和数据的双向绑定(v-model)
2017/06/23 Javascript
使用vue-router beforEach实现判断用户登录跳转路由筛选功能
2018/06/25 Javascript
使用Object.defineProperty如何巧妙找到修改某个变量的准确代码位置
2018/11/02 Javascript
AjaxFileUpload.js实现异步上传文件功能
2019/04/19 Javascript
node省市区三级数据性能测评实例分析
2019/11/06 Javascript
vue+导航锚点联动-滚动监听和点击平滑滚动跳转实例
2019/11/13 Javascript
javascript 易错知识点实例小结
2020/04/25 Javascript
Javascript实现打鼓效果
2021/01/29 Javascript
[02:57]DOTA2英雄基础教程 风行者
2014/01/16 DOTA
[01:07:22]2014 DOTA2华西杯精英邀请赛 5 24 DK VS VG加赛
2014/05/26 DOTA
[27:39]Ti4 循环赛第二日 LGD vs Fnatic
2014/07/11 DOTA
[53:18]Spirit vs Liquid Supermajor小组赛A组 BO3 第三场 6.2
2018/06/03 DOTA
Python读写txt文本文件的操作方法全解析
2016/06/26 Python
Python实现线程状态监测简单示例
2018/03/28 Python
python使用rpc框架gRPC的方法
2018/08/24 Python
详解pandas赋值失败问题解决
2020/11/29 Python
计算机应用专业推荐信
2013/11/13 职场文书
体育教育毕业生自荐信
2013/11/21 职场文书
北京英语导游词
2015/02/12 职场文书
拾金不昧表扬稿大全
2015/05/05 职场文书
上级领导检查欢迎词
2015/09/30 职场文书
关于践行三严三实的心得体会
2016/01/05 职场文书
Ajax常用封装库——Axios的使用
2021/05/08 Javascript
详解Go语言Slice作为函数参数的使用
2021/07/02 Golang
win10拖拽文件时崩溃怎么解决?win10文件不能拖拽问题解决方法
2022/08/14 数码科技