详解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停止输出代码
Jul 20 Javascript
几个常用的JavaScript字符串处理函数 - split()、join()、substring()和indexOf()
Jun 02 Javascript
jquery 提交值不为空的元素示例代码
May 10 Javascript
二叉树先序遍历的非递归算法具体实现
Jan 09 Javascript
Javascript实现可旋转的圆圈实例代码
Aug 04 Javascript
基于jQuery实现返回顶部实例代码
Jan 01 Javascript
学习掌握JavaScript中this的使用技巧
Aug 29 Javascript
使用JavaScript进行表单校验功能
Aug 01 Javascript
Angular2.0实现modal对话框的方法示例
Feb 18 Javascript
JavaScript强制类型转换和隐式类型转换操作示例
May 01 Javascript
微信小程序云开发之使用云数据库
May 17 Javascript
微信小程序自定义纯净模态框(弹出框)的实例代码
Mar 09 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
新版mysql+apache+php Linux安装指南
2006/10/09 PHP
php中邮箱地址正则表达式实现与详解
2012/04/24 PHP
php判断访问IP的方法
2015/06/19 PHP
CodeIgniter常用知识点小结
2016/05/26 PHP
TP(thinkPHP)框架多层控制器和多级控制器的使用示例
2018/06/13 PHP
Yii框架 session 数据库存储操作方法示例
2019/11/18 PHP
nodejs创建web服务器之hello world程序
2015/08/20 NodeJs
javascript事件委托的用法及其好处简析
2016/04/04 Javascript
浅述节点的创建及常见功能的实现
2016/12/15 Javascript
JavaScript实现时间表动态效果
2017/07/15 Javascript
JS设计模式之数据访问对象模式的实例讲解
2017/09/30 Javascript
Javascript网页抢红包外挂实现分享
2018/01/11 Javascript
vue-cli与webpack处理静态资源的方法及webpack打包的坑
2018/05/15 Javascript
基于mpvue的小程序项目搭建的步骤
2018/05/22 Javascript
JavaScript函数节流和函数去抖知识点学习
2018/07/31 Javascript
vue强制刷新组件的方法示例
2019/02/28 Javascript
[15:20]DOTA2-DPC中国联赛 正赛 Elephant vs Aster 选手采访
2021/03/11 DOTA
Python实现读取txt文件并画三维图简单代码示例
2017/12/09 Python
python读取文件名称生成list的方法
2018/04/27 Python
Python使用pymongo模块操作MongoDB的方法示例
2018/07/20 Python
python读取各种文件数据方法解析
2018/12/29 Python
Matplotlib使用字符串代替变量绘制散点图的方法
2020/02/17 Python
Python3.7安装pyaudio教程解析
2020/07/24 Python
python 用Matplotlib作图中有多个Y轴
2020/11/28 Python
阿迪达斯荷兰官方网站:adidas荷兰
2018/03/16 全球购物
大四自我鉴定
2014/02/08 职场文书
电子专业求职信
2014/06/19 职场文书
2014年人事部工作总结
2014/12/03 职场文书
2014普法依法治理工作总结
2014/12/18 职场文书
2015年社区平安建设工作总结
2015/05/13 职场文书
2015年财政局工作总结
2015/05/21 职场文书
mysql部分操作
2021/04/05 MySQL
游戏《铁拳》动画化!2022年年内播出
2022/03/21 日漫
Javascript的promise,async和await的区别详解
2022/03/24 Javascript
SQL SERVER中的流程控制语句
2022/05/25 SQL Server
分享很少见很有用的SQL功能CORRESPONDING
2022/08/05 MySQL