详解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全部源代码
May 04 Javascript
javascript 读取xml,写入xml 实现代码
Jul 10 Javascript
Jquery动态进行图片缩略的原理及实现
Aug 13 Javascript
javascript实现tab切换的四种方法
Nov 05 Javascript
基于jquery实现轮播焦点图插件
Mar 31 Javascript
jQuery DataTables插件自定义Ajax分页实例解析
Apr 28 Javascript
通过网页查看JS源码中汉字显示乱码的解决方法
Oct 26 Javascript
详解axios 全攻略之基本介绍与使用(GET 与 POST)
Sep 15 Javascript
vue父组件点击触发子组件事件的实例讲解
Feb 08 Javascript
jQuery 点击获取验证码按钮及倒计时功能
Sep 20 jQuery
vue项目中将element-ui table表格写成组件的实现代码
Jun 12 Javascript
javascript实现点击星星小游戏
Dec 24 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
十天学会php(2)
2006/10/09 PHP
php中将地址生成迅雷快车旋风链接的代码[测试通过]
2011/04/20 PHP
php空间不支持socket但支持curl时recaptcha的用法
2011/11/07 PHP
Zend Framework分页类用法详解
2016/03/22 PHP
ajax+php实现无刷新验证手机号的实例
2017/12/22 PHP
宝塔面板在NGINX环境中TP5.1如何运行?
2021/03/09 PHP
javascript基础的动画教程,直观易懂
2007/01/10 Javascript
asp.net HttpHandler实现图片防盗链
2009/11/09 Javascript
jQuery下的动画处理总结
2013/10/10 Javascript
JS获取随机数函数可自定义最小值最大值
2014/05/08 Javascript
原生js实现addClass,removeClass,hasClass方法
2016/04/27 Javascript
AngularJS指令详解及示例代码
2016/08/16 Javascript
微信小程序 在Chrome浏览器上运行以及WebStorm的使用
2016/09/27 Javascript
微信小程序云开发之新手环境配置
2019/05/16 Javascript
webpack DllPlugin xxx is not defined解决办法
2019/12/13 Javascript
js实现电灯开关效果
2021/01/19 Javascript
[39:52]2018DOTA2亚洲邀请赛 4.3 突围赛 EG vs Newbee 第一场
2018/04/04 DOTA
python列表操作使用示例分享
2014/02/21 Python
Python的subprocess模块总结
2014/11/07 Python
python字符串,数值计算
2016/10/05 Python
python之super的使用小结
2018/08/13 Python
使用pandas实现连续数据的离散化处理方式(分箱操作)
2019/11/22 Python
Python爬虫库BeautifulSoup获取对象(标签)名,属性,内容,注释
2020/01/25 Python
Django Admin后台添加数据库视图过程解析
2020/04/01 Python
Django之腾讯云短信的实现
2020/06/12 Python
opencv 阈值分割的具体使用
2020/07/08 Python
3D动画《斗罗大陆》上线当日播放过亿
2021/03/16 国漫
Html5自定义字体解决方法
2019/10/09 HTML / CSS
H5 video poster属性设置视频封面的方法
2020/05/25 HTML / CSS
新闻编辑自荐信
2013/11/03 职场文书
售后服务承诺书范文
2014/03/26 职场文书
个人工作总结范文2014
2014/11/07 职场文书
2014年计划生育协会工作总结
2014/11/14 职场文书
2014年科研工作总结
2014/12/03 职场文书
陶瓷类经典广告语集锦
2019/10/25 职场文书
Pandas数据结构之Series的使用
2022/03/31 Python