详解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 相关文章推荐
跨浏览器开发经验总结(四) 怎么写入剪贴板
May 13 Javascript
jQuery学习笔记[1] jQuery中的DOM操作
Dec 03 Javascript
js arguments,jcallee caller用法总结
Nov 30 Javascript
一个JavaScript防止表单重复提交的实例
Oct 21 Javascript
Bootstrap每天必学之下拉菜单
Nov 25 Javascript
精彩的Bootstrap案例分享 重点在注释!(选项卡、栅格布局)
Jul 01 Javascript
JS生成和下载二维码的代码
Dec 07 Javascript
vue实现父子组件之间的通信以及兄弟组件的通信功能示例
Jan 29 Javascript
关于AOP在JS中的实现与应用详解
May 06 Javascript
layer.confirm()右边按钮实现href的例子
Sep 27 Javascript
JS实现页面鼠标点击出现图片特效
Aug 19 Javascript
微信小程序 接入腾讯地图的两种写法
Jan 12 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 静态变量与自定义常量的使用方法
2010/01/26 PHP
PHP学习之正则表达式
2011/04/17 PHP
用js实现层随着内容大小动态渐变改变 推荐
2009/12/19 Javascript
JavaScript中的排序算法代码
2011/02/22 Javascript
JavaScript对象和字串之间的转换实例探讨
2013/04/21 Javascript
JavaScript设置IFrame高度自适应(兼容各主流浏览器)
2013/06/05 Javascript
jquery实现checkbox全选全不选的简单实例
2013/12/31 Javascript
js实现透明度渐变效果的方法
2015/04/10 Javascript
JQuery操作textarea,input,select,checkbox方法
2015/09/02 Javascript
全面解析Bootstrap表单使用方法(表单按钮)
2015/11/24 Javascript
bootstrap实现弹窗和拖动效果
2016/01/03 Javascript
Angular.js中用ng-repeat-start实现自定义显示
2016/10/18 Javascript
简单实现bootstrap导航效果
2017/02/07 Javascript
vue跨域解决方法
2017/10/15 Javascript
微信小程序实现搜索框功能及踩过的坑
2020/06/19 Javascript
[52:00]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 LGD vs Optic
2018/04/02 DOTA
python基础入门详解(文件输入/输出 内建类型 字典操作使用方法)
2013/12/08 Python
Python脚本实现代码行数统计代码分享
2015/03/10 Python
python编程测试电脑开启最大线程数实例代码
2018/02/09 Python
Python minidom模块用法示例【DOM写入和解析XML】
2019/03/25 Python
Python单元和文档测试实例详解
2019/04/11 Python
python写程序统计词频的方法
2019/07/29 Python
Python 异步协程函数原理及实例详解
2019/11/13 Python
如何基于Python实现自动扫雷
2020/01/06 Python
Python面向对象中类(class)的简单理解与用法分析
2020/02/21 Python
Python中if有多个条件处理方法
2020/02/26 Python
使用keras内置的模型进行图片预测实例
2020/06/17 Python
亚马逊新加坡官方网站:Amazon.sg
2020/03/25 全球购物
应届护士推荐信
2013/11/16 职场文书
酒店销售经理岗位职责
2014/01/31 职场文书
中国好声音华少广告词
2014/03/17 职场文书
公司年会策划方案
2014/05/17 职场文书
物流专业求职信
2014/06/30 职场文书
党支部书记四风问题整改措施
2014/09/24 职场文书
Python 如何利用ffmpeg 处理视频素材
2021/11/27 Python
《堡垒之夜》联动《刺客信条》 4月7日正式上线
2022/04/06 其他游戏