详解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 相关文章推荐
jquery的ajax()函数传值中文乱码解决方法介绍
Nov 08 Javascript
手机端页面rem宽度自适应脚本
May 20 Javascript
jQuery取消ajax请求的方法
Jun 09 Javascript
CSS中position属性之fixed实现div居中
Dec 14 Javascript
简单理解vue中track-by属性
Oct 26 Javascript
javascript history对象详解
Feb 09 Javascript
Restify中接入Socket.io报Error:Can’t set headers的错误解决
Mar 28 Javascript
JavaScript设置名字输入不合法的实现方法
May 23 Javascript
阿里大于短信验证码node koa2的实现代码(最新)
Sep 07 Javascript
原生JS实现多个小球碰撞反弹效果示例
Jan 31 Javascript
Vue运用transition实现过渡动画
May 06 Javascript
JS实现简易计算器
Feb 14 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使用ereg验证文件上传的方法
2014/12/16 PHP
Laravel中GraphQL接口请求频率实战记录
2020/09/01 PHP
PHP实现chrome表单请求数据转换为接口使用的json数据
2021/03/04 PHP
Prototype Hash对象 学习
2009/07/19 Javascript
屏蔽Flash右键信息的js代码
2010/01/17 Javascript
TBCompressor js代码压缩
2011/01/05 Javascript
JS关键字变色实现思路及代码
2013/02/21 Javascript
一个简单的JS鼠标悬停特效具体方法
2013/06/17 Javascript
JS 清除字符串数组中,重复元素的实现方法
2016/05/24 Javascript
JavaScript基础——使用Canvas绘图
2016/11/02 Javascript
jQuery实现点击某个div打开层,点击其他div关闭层实例分析(阻止冒泡)
2016/11/18 Javascript
详解angular中的作用域及继承
2017/05/31 Javascript
input file样式修改以及图片预览删除功能详细概括(推荐)
2017/08/17 Javascript
Vue2.0+ElementUI实现表格翻页的实例
2017/10/23 Javascript
js实现HTML中Select二级联动的实例
2018/01/05 Javascript
浅谈Node.js 子进程与应用场景
2018/01/24 Javascript
vue项目中导入swiper插件的方法
2018/01/30 Javascript
浅谈super-vuex使用体验
2018/06/25 Javascript
webpack 代码分离优化快速指北
2019/05/18 Javascript
vue.js的简单自动求和计算实例
2019/11/08 Javascript
Vue双向绑定实现原理与方法详解
2020/05/07 Javascript
vue实现信息管理系统
2020/05/30 Javascript
vue-quill-editor的使用及个性化定制操作
2020/08/04 Javascript
python框架中flask知识点总结
2018/08/17 Python
使用PyQt4 设置TextEdit背景的方法
2019/06/14 Python
在linux下实现 python 监控usb设备信号
2019/07/03 Python
Python 如何对文件目录操作
2020/07/10 Python
亚洲最大旅游体验平台:KKday
2017/10/21 全球购物
某公司.Net方向面试题
2014/04/24 面试题
大四自我鉴定范文
2013/10/06 职场文书
中医专业职业生涯规划书范文
2014/01/04 职场文书
创优争先心得体会
2014/09/11 职场文书
大班下学期幼儿评语
2014/12/30 职场文书
卫生保健工作总结2015
2015/05/18 职场文书
尼克胡哲观后感
2015/06/08 职场文书
开票证明
2015/06/23 职场文书