详解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中的prototype使用说明
Apr 13 Javascript
自定义ExtJS控件之下拉树和下拉表格附源码
Oct 15 Javascript
node.js中的http.response.getHeader方法使用说明
Dec 14 Javascript
使用JavaScript链式编程实现模拟Jquery函数
Dec 21 Javascript
安装使用Mongoose配合Node.js操作MongoDB的基础教程
Mar 01 Javascript
浅谈Vue.js 1.x 和 2.x 实例的生命周期
Jul 25 Javascript
基于ES6 Array.of的用法(实例讲解)
Sep 05 Javascript
Vuejs2 + Webpack框架里,模拟下载的实例讲解
Sep 05 Javascript
jQuery实现动画、消失、显现、渐出、渐入效果示例
Sep 06 jQuery
Vue 组件封装 并使用 NPM 发布的教程
Sep 30 Javascript
利用d3.js力导布局绘制资源拓扑图实例教程
Jan 08 Javascript
CKeditor富文本编辑器使用技巧之添加自定义插件的方法
Jun 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面向对象全攻略 (十五) 多态的应用
2009/09/30 PHP
解析php中die(),exit(),return的区别
2013/06/20 PHP
解析php安全性问题中的:Null 字符问题
2013/06/21 PHP
php连接与操作PostgreSQL数据库的方法
2014/12/25 PHP
php 使用ActiveMQ发送消息,与处理消息操作示例
2020/02/23 PHP
nginx 设置多个站跨域
2021/03/09 Servers
推荐20家国外的脚本下载网站
2011/04/28 Javascript
JS将光标聚焦在文本最后的实现代码
2014/03/28 Javascript
js获取日期:昨天今天和明天、后天
2014/06/11 Javascript
JavaScript替换当前页面的方法
2015/04/03 Javascript
js焦点文字滚动效果代码分享
2015/08/25 Javascript
JQuery实现图片轮播效果
2015/09/15 Javascript
javascript表单处理具体实现代码(表单、链接、按钮)
2016/05/07 Javascript
js与jquery分别实现tab标签页功能的方法
2016/11/18 Javascript
layui2.0使用table+laypage实现真分页
2019/07/27 Javascript
npm 语义版本控制详解
2019/09/10 Javascript
vue源码中的检测方法的实现
2019/09/26 Javascript
使用纯前端JavaScript实现Excel导入导出方法过程详解
2020/08/07 Javascript
详解ES6中class的实现原理
2020/10/03 Javascript
Python标准库shutil用法实例详解
2018/08/13 Python
python图形绘制奥运五环实例讲解
2019/09/14 Python
python tkinter基本属性详解
2019/09/16 Python
python的range和linspace使用详解
2019/11/27 Python
Django创建一个后台的基本步骤记录
2020/10/02 Python
详解CSS3原生支持div铺满浏览器的方法
2018/08/30 HTML / CSS
利用Canvas模仿百度贴吧客户端loading小球的方法示例
2017/08/13 HTML / CSS
三年级语文教学反思
2014/02/01 职场文书
运动会开幕式邀请函
2014/02/03 职场文书
爱心捐款倡议书范文
2014/05/12 职场文书
国防教育标语
2014/10/08 职场文书
2015年社区文体活动总结
2015/03/25 职场文书
2015年七一建党节活动方案
2015/05/05 职场文书
幼儿园2016年圣诞活动总结
2016/03/31 职场文书
Python实现随机生成迷宫并自动寻路
2021/06/13 Python
springcloud之Feign超时问题的解决
2021/06/24 Java/Android
MySQL时区造成时差问题
2022/04/13 MySQL