javascript中实现继承的三种方式:原型继承、借用构造函数继承、混合继承:

  1. /*
  2. js当中的继承
  3.  
  4. js中 构造函数 原型对象 实力对象的关系:
  5. 1 构造函数.prototype = 原型对象
  6. 2 原型对象.constructor = 构造函数(模板)
  7. 3 原型对象.isPrototypeOf(实例对象) 判断实例对象的原型是不是当前对象
  8. 4 构造函数 实力对象 是 类和对象的关系
  9. */
  10.  
  11. /*
  12. 1 原型继承
  13. 给子类构造函数的原型对象赋值为父类构造函数的实例
  14. 赋值之后产生的关系:
  15. 1 子类的原型对象是父类的一个实例 Son.prototype 是 new Father()
  16. 2 父类的方法和属性,子类可以在原型中得到
  17. 3 子类的原型对象的构造器是父类模板 Son.prototype.constructor 是 Father
  18. 4 子类的原型对象的原型对象是父类的原型对象 Son.prototype.prototype 是Father.prototype
  19. 原型继承的特点:
  20. 子类继承了父类所有属性方法发和 父类原型对象中的属性和方法
  21. 缺点: 不能在子类实例化对象的时候给父类的属性赋值,继承父类的值和子类对象实例化分开了。
  22. */
  23.  
  24. //父类构造函数
  25. function Father(name){
  26. this.name = name;
  27. }
  28. //父类原型对象
  29. Father.prototype={
  30. constructor: Father,
  31. id:10,
  32. sayName:function(){
  33. alert(this.name);
  34. }
  35. };
  36.  
  37. //子类构造函数
  38. function Son(age){
  39. this.age = age;
  40. }
  41. //子类原型对象 这一家子都姓张
  42. Son.prototype = new Father("张");
  43.  
  44. //子类的实例 能够使用父类的属性和方法
  45. var s1 = new Son(18);
  46. //s1.sayName(); //张
  47. //alert(s1.age); //18
  48.  
  49. /*
  50. 原型继承的特点:
  51. 子类继承了父类所有属性方法发和 父类原型对象中的属性和方法
  52. 缺点: 不能在子类实例化对象的时候给父类的属性赋值,继承父类的值和子类对象实例化分开了。
  53. */
  54.  
  55. /*
  56. 2 类继承(借用构造函数) 只继承父类的构造函数,父类的原型对象没有继承过来
  57. 利用call 或者apply进行函数绑定,借用父类构造函数的属性和方法
  58. */
  59. //父类构造函数
  60. function Father(name){
  61. this.name = name;
  62. }
  63. //父类原型对象 在子类中不能继承父类原型对象中的内容
  64. Father.prototype.id = 10;
  65.  
  66. //子类构造函数
  67. function Son(name,age){
  68. //name属性是父类的 不是子类的 借用父类的构造函数 把属性绑定给子类的实例对象
  69. Father.call(this,name);
  70. this.age = age;
  71. }
  72. //实例化子类对象 在这里可以直接给继承来的属性赋值
  73. var s2 = new Son("z3",18);
  74. //alert(s2.name); //z3 父类构造函数绑定来的属性
  75. //alert(s2.age); //18 子类自己的属性
  76.  
  77. /*
  78. 类继承(借用构造函数) 的特点:
  79. 优点: 能够在实例化子类对象时候给继承父类的属性赋值
  80. 缺点:父类的原型对象中的内容无法继承
  81. */
  82.  
  83. /*
  84. 3 混合继承:原型继承 和 借用构造函数继承 的混合
  85. 特点:
  86. 优点:1 能够在实例化子类对象的时候给继承来的属性赋值
  87. 2 能够继承父类的原型对象中的方法
  88. 缺点: 继承了两次父类的模版,分别是call绑定和子类原型对象赋值的时候
  89. 如果继承来的属性特别多,这会很耗费时间来维护
  90. */
  91. //父类
  92. function Father(name){
  93. this.name = name;
  94. }
  95. //父类的原型对象
  96. Father.prototype = {
  97. constructor:Father,
  98. id:10,
  99. sayName:function(){
  100. alert(this.name);
  101. }
  102. };
  103. //子类
  104. function Son(name,age){
  105. //借用父类构造函数 绑定子类方法 为子类继承来的属性赋值
  106. Father.call(this,name);
  107. this.age = age;
  108. }
  109. //原型继承 不传递参数,继承自父类的属性赋值交给借用父类构造函数去做
  110. Son.prototype = new Father();
  111.  
  112. //使用子类实例化对象
  113. var s3 = new Son("l4",20);
  114. //alert(s3.name); //父类属性
  115. //alert(s3.id); //父类原型对象的属性
  116. //alert(s3.age); //自己的属性
  117. //s3.sayName(); //父类原型对象中的方法
  118. /*
  119. 混合集成的特点:
  120. 优点:1 能够在实例化子类对象的时候给继承来的属性赋值
  121. 2 能够继承父类的原型对象中的方法
  122. 缺点: 继承了两次父类的模版,分别是call绑定和子类原型对象赋值的时候
  123. 如果继承来的属性特别多,这会很耗费时间来维护
  124. */

但是 上面三种方式 即使是混合继承也有弊端,下面用js模拟一下extends的继承方,来实现不会重复继承父类的构造函数:

  1. /*
  2. javascript模拟extends方法,
  3. 目的:
  4. 1子类实例化能够赋值继承来的属性
  5. 2 继承父类的原型对象
  6. 3 父类的构造函数只继承一次
  7. */
  8.  
  9. //1 我们模拟一个extends函数 用于实现类之间的继承 传入父类和子类
  10. function extend(son,father){
  11. //让子类继承父类的原型而不继承父类构造函数的内容
  12. var f = new Function(); //临时空函数,目的是函数内部是空的 但是原型是父类的原型
  13. f.prototype = father.prototype; //让空函数的原型指向父类的原型
  14. son.prototype = new f(); //让子类的原型指向一个空函数,空函数的原型是父类的原型,这就避免了父类构造函数的属性被重复实现
  15. //给子类添加一个superClass属性保存父类的原型对象,防止自己重写了父类方法后 无法调用父类原型对象中的方法
  16. son.superClass = father.prototype;
  17. //为父类原型对象添加构造器 如果父类原型对象忘记加构造器这里给他加上
  18. if(father.prototype.constructor == Object.prototype.constructor){
  19. father.prototype.constructor = father;
  20. }
  21. }
  22. //2 父类
  23. function Father(name){
  24. this.name = name;
  25. }
  26. //父类的原型对象
  27. Father.prototype = {
  28. constructor: Father,
  29. sayName:function(){
  30. alert(this.name);
  31. }
  32. };
  33.  
  34. //3 子类
  35. function Son(name,age){
  36. //借用构造函数:为子类绑定父类的构造函数中属性
  37. // Father.call(this , name); 这里不这样写,为了解耦,增加通用性,经过extentds函数之后,子类里面有了父类的属性
  38. Son.superClass.constructor.call(this , name); //Son.superClass是父类的原型对象,consturctor就是父类构造函数
  39. this.age = age;
  40. }
  41. //原型继承
  42. //Son.prototype = new Father(); //会再次绑定一次父类的构造函数 ,这里为了不重复继承父类构造函数,只继承父类原型对象 我们用自己
  43. //调用自己的继承方法 实现为子类继承父类的原型对象 而不继承父类的构造函数
  44.  
  45. extend(Son,Father);
  46.  
  47. //使用子类
  48. var s4 = new Son("haha",33);
  49. alert(s4.name); //haha 父类继承来的属性
  50. alert(s4.age); //33 自己的属性
  51. s4.sayName(); //haha 父类继承来的方法
  52. //重写父类方法
  53. s4.sayName = function(){
  54. alert("hello i am son");
  55. };
  56. s4.sayName(); //hello i am son 重写方法覆盖了父类的sayName
  57. //重写之后还想调用父类的方法 需要绑定一下 指定是我这个对象来调用
  58. Son.superClass.sayName.call(s4); //haha

javascript实现继承3种方式: 原型继承、借用构造函数继承、组合继承,模拟extends方法继承的更多相关文章

  1. JavaScript 创建对象的七种方式

    转自:xxxgitone.github.io/2017/06/10/JavaScript创建对象的七种方式/ JavaScript创建对象的方式有很多,通过Object构造函数或对象字面量的方式也可以 ...

  2. JavaScript创建对象的几种 方式

    //JavaScript创建对象的七种方式 //https://xxxgitone.github.io/2017/06/10/JavaScript%E5%88%9B%E5%BB%BA%E5%AF%B9 ...

  3. JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)

    JavaScript继承的6种方法 1,原型链继承 2,借用构造函数继承 3,组合继承(原型+借用构造) 4,原型式继承 5,寄生式继承 6,寄生组合式继承 1.原型链继承. <script t ...

  4. JavaScript构造函数+原型创建对象,原型链+借用构造函数模式继承父类练习

    虽然经常说是做前端开发的,但常常使用的技术反而是JQuery比较多一点.在JavaScript的使用上相对而言少些.尤其是在创建对象使用原型链继承上面,在项目开发中很少用到.所以今天做个demo练习一 ...

  5. [转载]javascript创建对象的几种方式

    原文链接:http://qingfeng825.iteye.com/blog/1935648 1. 工厂方法:能创建并返回特定类型对象的工厂函数(factory function). function ...

  6. JavaScript事件处理的三种方式(转)

    一.什么是JavaScript事件? 事件(Event)是JavaScript应用跳动的心脏,也是把所有东西粘在一起的胶水,当我们与浏览器中Web页面进行某些类型的交互时,事件就发生了. 事件可能是用 ...

  7. Flex(ActionScript)与JavaScript交互的两种方式示例

    随着各单位部门信息化进程的不断发展,互通互联.共享协调不断的被越来越多的客户所重视.很多新项目都要去必须能够集成已有的早期系统,至少也要能够实现交互对接.今天跟大家分享的是系统对接中ActionScr ...

  8. 原生javascript实现异步的7种方式

    1.$(document).ready 点评: 需要引用jquery :兼容所有浏览器. 2.标签的async=”async”属性 async的定义和用法(是HTML5的属性) async 属性规定一 ...

  9. JavaScript声明全局变量三种方式的异同

    JavaScript中声明变量很简单var(关键字)+变量名(标识符). 方式1 1 2 var test; var test = 5; 需注意的是该句不能包含在function内,否则是局部变量.这 ...

随机推荐

  1. php提交表单时判断 if($_POST[submit])与 if(isset($_POST[submit])) 的区别

    if(isset($_POST['submit'])) 它的意思是不是判断是否配置了$_POST['submit'] 这个变量呢?如果有这个变量 在执行其它代码 应该这样用if(isset($_POS ...

  2. AIX分页(交换)空间的监控

    1.分页和交换 这两个概念,很多人混为一回事儿,两者虽然有共性,但也有些差别.分页是进程的部分内容在RAM和磁盘的分页空间间移动,而交换是整个进程在RAM和磁盘的分页空间间移动,在将进程移到磁盘分页空 ...

  3. Java设计模式(六)Adapter适配器模式

    一.场景描述 “仪器数据采集器”包含采集数据以及发送数据给服务器两行为,则可定义“仪器数据采集器”接口,定义两方法“采集数据capture”和“发送数据sendData”. “PDF文件数据采集器”实 ...

  4. protobuf的下载、编译和使用

    一 背景 工作中临时需要使用 protobuf v3.0.2 做消息格式转换,折腾了很久才搞定,这里特意做一个记录. 二 准备工作 全程使用的电脑为公司的win7 64位旗舰版,已经预先安装VS201 ...

  5. protobuf(quickStart)

    1.简介 Protocol Buffers是Google开发一种数据描述语言,能够将数据进行序列化,可用于数据存储.通信协议等方面. 可以理解成更快.更简单.更小的JSON或者XML,区别在于Prot ...

  6. Docker学习笔记(一)

    什么是Docker? 1.基于Go语言开发的云开源项目,Docker的主要目标是通过对应用组件的 封装,分发,部署,运行等生命周期的管理,达到应用组件级别的 一次封装,到处运行. 2.可以将Docke ...

  7. ConcurrentHashMap 源码分析

    ConcurrentHashMap 源码分析 1. 前言    终于到这个类了,其实在前面很过很多次这个类,因为这个类代码量比较大,并且涉及到并发的问题,还有一点就是这个代码有些真的晦涩,不好懂.前前 ...

  8. 用SpringBoot搭建简单电商项目 01

    前几节呢,我们已经简单介绍了SpringBoot框架的使用,从这一节开始,我们尝试着使用SpringBoot框架来一步一步搭建一个简单电商项目.当然了,这不是真正的电商项目,你可以看成是一个CRUD案 ...

  9. Week04-面向对象设计与继承

    1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 is a关系 覆盖 Object 超级父类 继承 抽象类 多态 重载 static super private public p ...

  10. Markdown文本测试

    一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 1. 这是一 2. 这是二 这是无序符号 My Github 这是着重表示 这是斜体 一级粗体 二级斜体 cin >> a; c ...