详解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 相关文章推荐
说明你的Javascript技术很烂的五个原因
Apr 26 Javascript
jQuery 源码分析笔记(3) Deferred机制
Jun 19 Javascript
jquery自动填充勾选框即把勾选框打上true
Mar 24 Javascript
JS利用cookie记忆当前位置的防刷新导航效果
Oct 15 Javascript
用JS实现图片轮播效果代码(一)
Jun 26 Javascript
javascript 数据存储的常用函数总结
Jun 01 Javascript
vue-router+vuex addRoutes实现路由动态加载及菜单动态加载
Sep 28 Javascript
vue.js中$set与数组更新方法
Mar 08 Javascript
vue观察模式浅析
Sep 25 Javascript
使用pkg打包Node.js应用的方法步骤
Oct 19 Javascript
js+HTML5 canvas 实现简单的加载条(进度条)功能示例
Jul 16 Javascript
element-ui中el-upload多文件一次性上传的实现
Dec 02 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
1 Tube Radio
2021/03/02 无线电
树型结构列出指定目录里所有文件的PHP类
2006/10/09 PHP
php输出echo、print、print_r、printf、sprintf、var_dump的区别比较
2013/06/21 PHP
php中sql注入漏洞示例 sql注入漏洞修复
2014/01/24 PHP
跟我学Laravel之路由
2014/10/15 PHP
源码分析 Laravel 重复执行同一个队列任务的原因
2017/12/25 PHP
php报错502badgateway解决方法
2019/10/11 PHP
php的无刷新操作实现方法分析
2020/02/28 PHP
禁止JQuery中的load方法装载IE缓存中文件的方法
2009/09/11 Javascript
jQuery的attr与prop使用介绍
2013/10/10 Javascript
javascript实现节点(div)名称编辑
2014/12/17 Javascript
深入理解$.each和$(selector).each
2016/05/15 Javascript
JS常用算法实现代码
2016/11/14 Javascript
利用jquery获取select下拉框的值
2016/11/23 Javascript
javascript中活灵活现的Array对象详解
2016/11/30 Javascript
jQuery实现判断控件是否显示的方法
2017/01/11 Javascript
如何使用bootstrap框架 bootstrap入门必看!
2017/04/13 Javascript
vue实现的上传图片到数据库并显示到页面功能示例
2018/03/17 Javascript
Vue.js实现开发购物车功能的方法详解
2019/02/22 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
2019/08/29 Javascript
使用pkg打包ThinkJS项目的方法步骤
2019/12/30 Javascript
使用Taro实现小程序商城的购物车功能模块的实例代码
2020/06/05 Javascript
Python中实现对list做减法操作介绍
2015/01/09 Python
Scrapy爬虫实例讲解_校花网
2017/10/23 Python
Python 十六进制整数与ASCii编码字符串相互转换方法
2018/07/09 Python
Python 中的lambda函数介绍
2018/10/10 Python
Python字典深浅拷贝与循环方式方法详解
2020/02/09 Python
python音频处理的示例详解
2020/12/23 Python
Foot Locker意大利官网:全球领先的运动鞋和服装零售商
2017/05/30 全球购物
Expedia英国:全球最大的在线旅游公司
2017/09/07 全球购物
美国孕妇装购物网站:Motherhood Maternity
2019/09/22 全球购物
应届中专生自荐书范文
2014/02/13 职场文书
倡议书的格式写法
2015/04/28 职场文书
社区党务工作总结2015
2015/05/19 职场文书
红色经典观后感
2015/06/18 职场文书
springboot读取resources下文件的方式详解
2022/06/21 Java/Android