详解JavaScript之ES5的继承


Posted in Javascript onJuly 08, 2020

自从有了ES6的继承后,ES5的继承也退出了舞台,在实际开发也不会用得着,但在面试或许用的着;

先看看ES6的继承

class Father{

      constructor(a){
        console.log(a);
      }
      play(){
        console.log("aaa");
      }
      static run(){
        console.log("static");
      }
    }
    class Son extends Father{
      constructor(){
        super();
      }
    }
    var s=new Son();
    s.play();
    Father.run()
    Son.run();

在ES6里只需要使用extends和super关键字即可继承父类的方法和属性(包括静态)

在ES5里没有这些关键字

ES5的继承

ES5的五种种继承方式:

  1. 对象冒充继承
  2. 原型链继承
  3. 组合继承
  4. 原型式继承
  5. 寄生式继承(重要)

对象冒充继承

function Father(_r){
      this.r=_r;
      console.log("aa");
      console.log(this.r);
    }
    Father.a=3;
    Father.run=function(){
      console.log(Box.a);
    }
function Son(){
      Father.call(this,3);//改变this的指向,执行父类构造函数并传参到父类
    }
    var b=new Son();//"aa",3
    b.run();//TypeError

通过call或apply改变this指向,并执行了父类的构造函数

缺点:只能继承超类的构造函数,无法继承原型链上的方法

原型链继承

function Father(){
  console.log("aa");
    }
Father.prototype.b=10;
    Father.prototype.play=function(){
      console.log(this.b);
    }
    Son.prototype=new Father();
    function Son(){
    }
    var b=new Son();
    b.play();//10

将父类的实例化对象赋值给子类的原型上实现的继承

缺点:覆盖子类原有的属性和方法,只能执行父类的属性和方法,无法执行父类的构造函数

组合继承

前面的两种继承(冒充,原型链)各有特点,把这两种继承组合起来称为组合继承

function Father(_r){
      this.r=_r;
      console.log("aa");
    }
function Son(_r){
      Father.call(this,_r);//冒充,改变父类的this指向子类
    }
Son.prototype=new Father(3);//原型链继承
 var c=new Son(10);

使用原型链继承了父类的属性和方法,使用对象冒充继承了父类的构造函数

看起来很不错的样子,但这并不是完美的继承方式;

缺点:会覆盖子类原有的属性和方法,因为原型链继承会将父类实例化,提前执行了一次父类构造函数;当子类实例化对象后,实际上是执行了两次父类的构造函数。

使用场景:子类原本没有属性和方法,父类构造函数没有内容。

原型式继承

为了解决执行两次父类构造函数使用了一个中介,在继承时就不会执行父类的构造函数

function Father(_a){
      this.a=_a
    }
    Father.prototype.play=function(){
      console.log("aaa");
    }
      function Agent(){

      }
      Agent.prototype=Father.prototype;
      function Son(){

      }
      Son.prototype=new Agent();
      var o=new Son();
      o.play();//aaa

使用了Agent的类作为中介,将父类的原型复制后,再进行实例化继承不会执行父类的构造函数;

缺点:虽然解决了构造函数执行两次的问题,但是使用该方法继承后,构造函数一次也不会执行。

寄生式继承(完美继承)

封装了一个extend方法,该方法传入两个参数,分别是父类和子类

function extend(subClass, supClass) {
     function Agent() {}
     Agent.prototype = supClass.prototype;
     var o = subClass.prototype;
     subClass.prototype = new Agent();
     if (Object.assign) {
      Object.assign(subClass.prototype, o);
     } else {
      if (Object.getOwnPropertyNames) {
       var names = Object.getOwnPropertyNames(o);
       for (var i = 0; i < names.length; i++) {
        var desc = Object.getOwnPropertyDescriptor(names[i]);
        Object.defineProperty(subClass.prototype, names[i], desc);
       }
      } else {
       for (var prop in o) {
        subClass.prototype[prop] = o[prop];
       }
      }
     }
     subClass.prototype.constructor = subClass; //防止子类的构造函数被覆盖
     if (supClass.prototype.constructor === Object) {
      supClass.prototype.constructor = supClass; //防止父类类的构造函数被覆盖
     }
     // 存储父类,方便继承构造函数调用
     subClass.prototype.superClass = supClass;
    }
 //调用
    function Father(_r) {
     this.r = _r;
     console.log("Father");
    }
    Father.prototype.play = function () {
     console.log("play game");
    };
    function Ball(_r) {
     this.superClass.call(this, _r);
    }
    var s = new Son(10);//Father
    s.play();//play game

extend方法,使用了Object.assgin、Object.getOwnPropertyNames、Object.getOwnPropertyDescriptor、Object.defineProperty都存在兼容问题,所以进行了判断。

该方法继承集合了前四种的优点,实现了ES5的完美继承;

结语:

ES5对比ES6的继承,麻烦太多太多,以后的实际工作也不会使用;

但是在面试的时候,面试官可能会问,多学一点总没错。

以上就是详解JavaScript之ES5的继承的详细内容,更多关于JavaScript ES5的继承的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
javascript面向对象之Javascript 继承
May 04 Javascript
简单实现异步编程promise模式
Jul 31 Javascript
JS简单循环遍历json数组的方法
Apr 22 Javascript
laydate 显示结束时间不小于开始时间的实例
Aug 11 Javascript
浅析node Async异步处理模块用例分析及常用方法介绍
Nov 17 Javascript
Vue-router 中hash模式和history模式的区别
Jul 24 Javascript
jQuery.validate.js表单验证插件的使用代码详解
Oct 22 jQuery
JS实现点击li标签弹出对应的索引功能【案例】
Feb 18 Javascript
基于JS开发微信网页录音功能的实例代码
Apr 30 Javascript
javascript(基于jQuery)实现鼠标获取选中的文字示例【测试可用】
Oct 26 jQuery
解决vue bus.$emit触发第一次$on监听不到问题
Jul 28 Javascript
详解vue修改elementUI的分页组件视图没更新问题
Nov 13 Javascript
jQuery使用jsonp实现百度搜索的示例代码
Jul 08 #jQuery
微信小程序拖拽排序列表的示例代码
Jul 08 #Javascript
基于javascript canvas实现五子棋游戏
Jul 08 #Javascript
深度解读vue-resize的具体用法
Jul 08 #Javascript
详解React 条件渲染
Jul 08 #Javascript
webpack5 联邦模块介绍详解
Jul 08 #Javascript
实例讲解React 组件
Jul 07 #Javascript
You might like
PHPMailer安装方法及简单实例
2008/11/25 PHP
php数组的概述及分类与声明代码演示
2013/02/26 PHP
分享一则PHP定义函数代码
2015/02/26 PHP
微信JSSDK分享功能图文实例详解
2019/04/08 PHP
JavaScript Object的extend是一个常用的功能
2009/12/02 Javascript
jQuery Tab插件 用于在Tab中显示iframe,附源码和详细说明
2011/06/27 Javascript
JavaScript计算字符串中每个字符出现次数的小例子
2013/07/02 Javascript
JavaScript实现的背景自动变色代码
2015/10/17 Javascript
Js类的静态方法与实例方法区分及jQuery拓展的两种方法
2016/06/03 Javascript
老生常谈onBlur事件与onfocus事件(js)
2016/07/09 Javascript
AngularJS 路由详解和简单实例
2016/07/28 Javascript
详解Angular2中的编程对象Observable
2016/09/17 Javascript
微信小程序 location API实例详解
2016/10/02 Javascript
webpack+vuex+axios 跨域请求数据的示例代码
2018/03/06 Javascript
基于JS实现操作成功之后自动跳转页面
2020/09/25 Javascript
[00:35]DOTA2上海特级锦标赛 EG战队宣传片
2016/03/04 DOTA
[00:32]2018DOTA2亚洲邀请赛Newbee出场
2018/04/03 DOTA
[06:45]2018DOTA2亚洲邀请赛 4.5 SOLO赛 Sccc vs Maybe
2018/04/06 DOTA
Python实现excel转sqlite的方法
2017/07/17 Python
利用numpy实现一、二维数组的拼接简单代码示例
2017/12/15 Python
漂亮的Django Markdown富文本app插件的实现
2019/01/02 Python
浅谈pyqt5中信号与槽的认识
2019/02/17 Python
python3 实现的对象与json相互转换操作示例
2019/08/17 Python
解决Atom安装Hydrogen无法运行python3的问题
2019/08/28 Python
python实现贪吃蛇游戏源码
2020/03/21 Python
碧欧泉法国官网:Biotherm法国
2019/10/23 全球购物
乌克兰鞋类购物网站:Eobuv.com.ua
2020/11/28 全球购物
linux面试题参考答案(2)
2015/12/06 面试题
do you have any Best Practice for testing
2016/06/04 面试题
村长贪污检举信
2014/04/04 职场文书
贷款承诺书范文
2014/05/19 职场文书
乡镇领导班子批评与自我批评材料
2014/09/23 职场文书
大客户经理岗位职责
2015/04/09 职场文书
2015年房产销售工作总结范文
2015/05/22 职场文书
2016大一新生军训心得体会
2016/01/11 职场文书
详解java如何集成swagger组件
2021/06/21 Java/Android