详解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中剪贴板兼容性、判断复制成功或失败
Mar 09 Javascript
Js组件的一些写法
Sep 10 Javascript
判断用户的在线状态 onbeforeunload事件
Mar 05 Javascript
jQuery提交表单ajax查询实例代码
Oct 07 Javascript
jQuery仿Flash上下翻动的中英文导航菜单实例
Mar 10 Javascript
jQuery实现表格行上移下移和置顶的方法
May 22 Javascript
jquery获得当前html页面源码的方法
Jul 14 Javascript
详解webpack进阶之插件篇
Jul 06 Javascript
vue移动端下拉刷新和上拉加载的实现代码
Sep 08 Javascript
VUE引入第三方js包及调用方法讲解
Mar 01 Javascript
layui按条件隐藏表格列的实例
Sep 19 Javascript
Laravel 如何在blade文件中使用Vue组件的示例代码
Jun 28 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
Nigma vs Alliance BO5 第一场2.14
2021/03/10 DOTA
对YUI扩展的Gird组件 Part-1
2007/03/10 Javascript
Web 前端设计模式--Dom重构 提高显示性能
2010/10/22 Javascript
JavaScript 原型链学习总结
2010/10/29 Javascript
jquery(live)中File input的change方法只起一次作用的解决办法
2011/10/21 Javascript
说说JSON和JSONP 也许你会豁然开朗
2012/09/02 Javascript
使用js画图之画切线
2015/01/12 Javascript
Google 地图控件集详解及实例代码
2016/08/06 Javascript
jquery html5 视频播放控制代码
2016/11/06 Javascript
javascript 注释代码的几种方法总结
2017/01/04 Javascript
微信小程序实现获取自己所处位置的经纬度坐标功能示例
2017/11/30 Javascript
JS实现全屏预览F11功能的示例代码
2018/07/23 Javascript
对VUE中的对象添加属性
2018/09/18 Javascript
小白教程|一小时上手最流行的前端框架vue(推荐)
2019/04/10 Javascript
详解如何探测小程序返回到webview页面
2019/05/14 Javascript
VUE路由动态加载实例代码讲解
2019/08/26 Javascript
微信小程序点击保存图片到本机功能
2019/12/13 Javascript
vue组件库的在线主题编辑器的实现思路
2020/04/03 Javascript
[02:30]联想杯DOTA2完美世界全国高校联赛—北京站现场
2015/11/16 DOTA
Pycharm学习教程(7)虚拟机VM的配置教程
2017/05/04 Python
Python实现针对中文排序的方法
2017/05/09 Python
Python微信企业号开发之回调模式接收微信端客户端发送消息及被动返回消息示例
2017/08/21 Python
Python矩阵常见运算操作实例总结
2017/09/29 Python
Python中extend和append的区别讲解
2019/01/24 Python
pycharm 批量修改变量名称的方法
2019/08/01 Python
pandas dataframe 中的explode函数用法详解
2020/05/18 Python
学习交流会主持词
2014/04/01 职场文书
难忘的一课教学反思
2014/04/30 职场文书
学校教研活动总结
2014/07/02 职场文书
真诚的求职信
2014/07/04 职场文书
学校拾金不昧表扬信
2015/01/16 职场文书
严以修身专题学习研讨会发言材料
2015/11/09 职场文书
《领导干部从政道德启示录》学习心得体会
2016/01/20 职场文书
《狮子和鹿》教学反思
2016/02/16 职场文书
导游词之麻姑仙境
2019/11/18 职场文书
Vue通过懒加载提升页面响应速度
2021/05/10 Vue.js