详解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 相关文章推荐
prototype 1.5 &amp; scriptaculous 1.6.1 学习笔记
Sep 07 Javascript
很多人都是用下面的js刷新站IP和PV
Sep 05 Javascript
JavaScript实现网页截图功能
Oct 16 Javascript
javascript判断css3动画结束 css3动画结束的回调函数
Mar 10 Javascript
基于JavaScript实现Json数据根据某个字段进行排序
Nov 24 Javascript
jQuery div拖拽用法实例
Jan 14 Javascript
jQuery select自动选中功能实现方法分析
Nov 28 Javascript
微信小程序搜索组件wxSearch实例详解
Jun 08 Javascript
javascript函数的节流[throttle]与防抖[debounce]
Nov 15 Javascript
vue element-ui table表格滚动加载方法
Mar 02 Javascript
JS实现常见的查找、排序、去重算法示例
May 21 Javascript
JS代码屏蔽F12,右键,粘贴,复制,剪切,选中,操作实例
Sep 17 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
中国第一家无线电行
2021/03/01 无线电
mysql 的 like 问题,超强毕杀记!!!
2007/01/18 PHP
php 批量查询搜狗sogou代码分享
2015/05/17 PHP
浅谈PHP中的错误处理和异常处理
2017/02/04 PHP
PHP第三方登录―QQ登录实现方法
2017/02/06 PHP
PHP curl 或 file_get_contents 获取需要授权页面的方法
2017/05/05 PHP
jQuery模拟点击A标记示例参考
2014/04/17 Javascript
js中confirm实现执行操作前弹出确认框的方法
2014/11/01 Javascript
JS数组array元素的添加和删除方法代码实例
2015/06/01 Javascript
angularjs学习笔记之简单介绍
2015/09/26 Javascript
jquery实现定时自动轮播特效
2015/12/10 Javascript
深入浅析JSON.parse()、JSON.stringify()和eval()的作用详解
2016/04/03 Javascript
javascript RegExp 使用说明
2016/05/21 Javascript
使用Curl命令查看请求响应时间方法
2016/11/04 Javascript
React全家桶环境搭建过程详解
2018/05/18 Javascript
vue v-for循环重复数据无法添加问题解决方法【加track-by='索引'】
2019/03/15 Javascript
Chrome插件开发系列一:弹窗终结者开发实战
2020/10/02 Javascript
windows下安装python paramiko模块的代码
2013/02/10 Python
Python内置函数的用法实例教程
2014/09/08 Python
用Python写一个无界面的2048小游戏
2016/05/24 Python
MySQL适配器PyMySQL详解
2017/09/20 Python
TF-IDF与余弦相似性的应用(一) 自动提取关键词
2017/12/21 Python
详解Django+Uwsgi+Nginx的生产环境部署
2018/06/25 Python
Python中类的创建和实例化操作示例
2019/02/27 Python
Python创建文件夹与文件的快捷方法
2020/12/08 Python
美国成衣女装品牌:CHICO’S
2016/09/19 全球购物
网络方面基础面试题
2012/11/16 面试题
大一新生军训时的自我评价分享
2013/12/05 职场文书
家具公司总经理岗位职责
2014/07/08 职场文书
支部书记四风对照材料
2014/08/28 职场文书
本科毕业论文导师评语
2014/12/31 职场文书
2015年电工工作总结
2015/04/10 职场文书
公积金贷款承诺书
2015/04/30 职场文书
保险公司增员口号
2015/12/25 职场文书
一条慢SQL语句引发的改造之路
2022/03/16 MySQL
Python可视化神器pyecharts之绘制箱形图
2022/07/07 Python