详解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 相关文章推荐
很多人都是用下面的js刷新站IP和PV
Sep 05 Javascript
JQuery中form验证出错信息的查看方法
Oct 08 Javascript
jquery基础教程之数组使用详解
Mar 10 Javascript
JavaScript实现给定时间相加天数的方法
Jan 25 Javascript
javascript html5 canvas实现可拖动省份的中国地图
Mar 11 Javascript
Bootstrap Table的使用总结
Oct 08 Javascript
AngularJS 与Bootstrap实现表格分页实例代码
Oct 14 Javascript
js实现首屏延迟加载实现方法 js实现多屏单张图片延迟加载效果
Jul 17 Javascript
微信小程序使用checkbox显示多项选择框功能【附源码下载】
Dec 11 Javascript
详解axios中封装使用、拦截特定请求、判断所有请求加载完毕)
Apr 09 Javascript
vue中利用simplemde实现markdown编辑器(增加图片上传功能)
Apr 29 Javascript
jQuery+ThinkPHP实现图片上传
Jul 23 jQuery
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
跟我学Laravel之安装Laravel
2014/10/15 PHP
PHP中key和current,next的联合运用实例分析
2016/03/29 PHP
jQuery使用手册之 事件处理
2007/03/24 Javascript
JS 控制非法字符的输入代码
2009/12/04 Javascript
JQuery中each()的使用方法说明
2010/08/19 Javascript
JQERY limittext 插件0.2版(长内容限制显示)
2010/08/27 Javascript
jquery定时滑出可最小化的底部提示层特效代码
2013/10/02 Javascript
JS实现的数组全排列输出算法
2015/03/19 Javascript
100多个基础常用JS函数和语法集合大全
2017/02/16 Javascript
Bootstrap表格制作代码
2017/03/17 Javascript
angularjs封装$http为factory的方法
2017/05/18 Javascript
AngularJS页面带参跳转及参数解析操作示例
2017/06/28 Javascript
Javascript中将变量转换为字符串的三种方法
2017/09/19 Javascript
react-native-video实现视频全屏播放的方法
2018/03/19 Javascript
express 项目分层实践详解
2018/12/10 Javascript
[03:49]DOTA2 2015国际邀请赛中国区预选赛第二日现场百态
2015/05/27 DOTA
[02:00]DAC2018主宣传片——龙征四海,剑问东方
2018/03/20 DOTA
[42:52]Optic vs Serenity 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
python通过smpt发送邮件的方法
2015/04/30 Python
Python类定义和类继承详解
2015/05/08 Python
简介Python设计模式中的代理模式与模板方法模式编程
2016/02/02 Python
python实现红包裂变算法
2016/02/16 Python
Python用5行代码写一个自定义简单二维码
2018/10/21 Python
Python 硬币兑换问题
2019/07/29 Python
Python3使用xlrd、xlwt处理Excel方法数据
2020/02/28 Python
html5时钟实现代码
2010/10/22 HTML / CSS
法国时尚品牌乐都特瑞士站:La Redoute瑞士
2016/09/05 全球购物
《珍珠泉》教学反思
2014/02/20 职场文书
车队司机自我鉴定
2014/03/02 职场文书
党委领导班子整改方案
2014/09/30 职场文书
2014年综治维稳工作总结
2014/11/17 职场文书
2014年电教工作总结
2014/12/19 职场文书
2015年后勤工作总结范文
2015/04/08 职场文书
幼儿园小班教师随笔
2015/08/14 职场文书
《鸡兔同笼》教学反思
2016/02/19 职场文书
源码解读Spring-Integration执行过程
2021/06/11 Java/Android