详解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模拟多线程
Feb 07 Javascript
top.location.href 没有权限 解决方法
Aug 05 Javascript
javascript中的取反再取反~~没有意义
Apr 06 Javascript
jquery实现倒计时代码分享
Jun 13 Javascript
jQuery实现企业网站横幅焦点图切换功能实例
Apr 30 Javascript
简介JavaScript中fixed()方法的使用
Jun 08 Javascript
JavaScript 深层克隆对象详解及实例
Nov 03 Javascript
jquery实现回车键触发事件(实例讲解)
Nov 21 jQuery
vue和react等项目中更简单的实现展开收起更多等效果示例
Feb 22 Javascript
Vue.js实现大转盘抽奖总结及实现思路
Oct 09 Javascript
Vue ​v-model相关知识总结
Jan 28 Vue.js
vue route新窗口跳转页面并且携带与接收参数
Apr 10 Vue.js
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生成HTML静态页面实例代码
2008/08/31 PHP
分享一段php获取linux服务器状态的代码
2014/05/27 PHP
php字符比较函数similar_text、strnatcmp与strcasecmp用法分析
2014/11/18 PHP
PHP排序算法之冒泡排序(Bubble Sort)实现方法详解
2018/04/20 PHP
php将从数据库中获得的数据转换成json格式并输出的方法
2018/08/21 PHP
用js脚本控制asp.net下treeview的NodeCheck的实现代码
2010/03/02 Javascript
js操作iframe的一些方法介绍
2013/06/25 Javascript
input链接页面、打开新网页等等的具体实现
2013/12/30 Javascript
jquery实现拖拽调整Div大小
2015/01/30 Javascript
基于jQuery和hwSlider实现内容左右滑动切换效果附源码下载(一)
2016/06/22 Javascript
微信小程序 实战小程序实例
2016/10/08 Javascript
详解javascript中对数据格式化的思考
2017/01/23 Javascript
详解Angular 开发环境搭建
2017/06/22 Javascript
vue-cli axios请求方式及跨域处理问题
2018/03/28 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
2020/02/09 Javascript
[02:40]DOTA2英雄基础教程 先知
2013/11/29 DOTA
python操作摄像头截图实现远程监控的例子
2014/03/25 Python
Python实现的基数排序算法原理与用法实例分析
2017/11/23 Python
python读写LMDB文件的方法
2018/07/02 Python
python实战教程之自动扫雷
2018/07/13 Python
Python实现的tcp端口检测操作示例
2018/07/24 Python
Python反射和内置方法重写操作详解
2018/08/27 Python
对numpy中向量式三目运算符详解
2018/10/31 Python
详解Python的数据库操作(pymysql)
2019/04/04 Python
python实现电子书翻页小程序
2019/07/23 Python
Python编译为二进制so可执行文件实例
2019/12/23 Python
详解python常用命令行选项与环境变量
2020/02/20 Python
opencv python 图片读取与显示图片窗口未响应问题的解决
2020/04/24 Python
深入理解css属性的选择对动画性能的影响
2016/04/20 HTML / CSS
美味咖啡的顶级烘焙师:Cafe Britt
2018/03/15 全球购物
大学生就业求职信
2014/06/12 职场文书
MYSQL 无法识别中文的永久解决方法
2021/06/03 MySQL
使用pycharm运行flask应用程序的详细教程
2021/06/07 Python
Java多条件判断场景中规则执行器的设计
2021/06/26 Java/Android
PHP面试题 wakeup魔法 Ezpop pop序列化与反序列化
2022/04/11 PHP
小程序实现侧滑删除功能
2022/06/25 Javascript