详解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 相关文章推荐
IE与FireFox的兼容性问题分析
Apr 22 Javascript
javascript jscroll模拟html元素滚动条
Dec 18 Javascript
js关闭父窗口时关闭子窗口
Apr 01 Javascript
一个支付页面DEMO附截图
Jul 22 Javascript
JavaScript实现的简单幂函数实例
Apr 17 Javascript
jQuery实现鼠标点击弹出渐变层的方法
Jul 09 Javascript
javascript基本常用排序算法解析
Sep 27 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
Aug 20 Javascript
从零开始搭建vue移动端项目到上线的步骤
Oct 15 Javascript
详解element-ui日期时间选择器的日期格式化问题
Apr 08 Javascript
JS开发常用工具函数(小结)
Jul 04 Javascript
Canvas三种动态画圆实现方法说明(小结)
Apr 16 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
ASP知识讲座四
2006/10/09 PHP
文件系统基本操作类
2006/11/23 PHP
PHP 程序授权验证开发思路
2009/07/09 PHP
用PHP提取中英文词语以及数字的首字母的方法介绍
2013/04/23 PHP
基于php常用正则表达式的整理汇总
2013/06/08 PHP
linux下使用crontab实现定时PHP计划任务失败的原因分析
2014/07/05 PHP
php处理静态页面:页面设置缓存时间实例
2017/06/22 PHP
php中加密解密DES类的简单使用方法示例
2020/03/26 PHP
jQuery控制图片的hover效果(smartRollover.js)
2012/03/18 Javascript
js轮盘抽奖实例分析
2020/04/17 Javascript
实例解析angularjs的filter过滤器
2016/12/14 Javascript
原生JS实现图片懒加载(lazyload)实例
2017/06/13 Javascript
Vue自定义弹窗指令的实现代码
2018/08/13 Javascript
微信小程序实现简单评论功能
2018/11/28 Javascript
使用Jenkins部署React项目的方法步骤
2019/03/11 Javascript
ZK中使用JS读取客户端txt文件内容问题
2019/11/07 Javascript
详解ES6 扩展运算符的使用与注意事项
2020/11/12 Javascript
基于python的汉字转GBK码实现代码
2012/02/19 Python
python改变日志(logging)存放位置的示例
2014/03/27 Python
使用python开发vim插件及心得分享
2014/11/04 Python
python rsa 加密解密
2017/03/20 Python
Python使用django搭建web开发环境
2017/06/09 Python
Python namedtuple命名元组实现过程解析
2020/01/08 Python
Python单例模式的四种创建方式实例解析
2020/03/04 Python
python中strip(),lstrip(),rstrip()函数的使用讲解
2020/11/17 Python
新西兰杂志订阅:isubscribe
2019/08/26 全球购物
System.Array.CopyTo()和System.Array.Clone()有什么区别
2016/06/20 面试题
介绍一下Java中标识符的命名规则
2014/02/03 面试题
运动会广播稿500字
2014/01/28 职场文书
致铅球运动员加油稿
2014/02/13 职场文书
爱国演讲稿400字
2014/05/07 职场文书
贷款收入证明格式
2015/06/24 职场文书
MySQL创建高性能索引的全步骤
2021/05/02 MySQL
python执行js代码的方法
2021/05/13 Python
Redis可视化客户端小结
2021/06/10 Redis
MySQL 数据库 增删查改、克隆、外键 等操作
2022/05/11 MySQL