详解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 相关文章推荐
刷新页面实现方式总结(HTML,ASP,JS)
Nov 13 Javascript
js判断样式className同时增加class或删除class
Jan 30 Javascript
关于jQuery object and DOM element
Apr 15 Javascript
JS截取字符串常用方法整理及使用示例
Oct 18 Javascript
js设置组合快捷键/tabindex功能的方法
Nov 21 Javascript
jquery+ajax实现注册实时验证实例详解
Dec 08 Javascript
jquery 判断selection range 是否在容器中的简单实例
Aug 02 Javascript
微信和qq时间格式模板实例详解
Oct 21 Javascript
Bootstrap基本组件学习笔记之缩略图(13)
Dec 08 Javascript
JavaScript中数据类型转换总结
Dec 25 Javascript
微信小程序网络封装(简单高效)
Aug 06 Javascript
Vue Autocomplete 自动完成功能简单示例
May 25 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+DBM的同学录程序(3)
2006/10/09 PHP
不用写JS也能使用EXTJS视频演示
2008/12/29 Javascript
Javascript Tab 导航插件 (23个)
2009/06/11 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(一)让静态人物动起来
2013/01/23 Javascript
自定义右键属性覆盖浏览器默认右键行为实现代码
2013/02/02 Javascript
jQuery 淡入淡出 png图在ie8下有黑色边框的解决方法
2013/03/05 Javascript
Javascript跨域请求的4种解决方式
2013/03/17 Javascript
jqGrid日期格式的判断示例代码(开始日期与结束日期)
2013/11/08 Javascript
js正则表达式注册页面表单验证
2016/10/11 Javascript
JS实现的几个常用算法
2016/11/12 Javascript
浅谈pc端rem字体设置的问题
2017/08/03 Javascript
JavaScript中的一些隐式转换和总结(推荐)
2017/12/22 Javascript
JS实现的A*寻路算法详解
2018/12/14 Javascript
微信小程序websocket实现即时聊天功能
2019/05/21 Javascript
js 闭包深入理解与实例分析
2020/03/19 Javascript
Python六大开源框架对比
2015/10/19 Python
Python有序字典简单实现方法示例
2017/09/28 Python
python基础之包的导入和__init__.py的介绍
2018/01/08 Python
浅谈numpy库的常用基本操作方法
2018/01/09 Python
Python线程同步的实现代码
2018/10/03 Python
python获取服务器响应cookie的实例
2018/12/28 Python
Python imread、newaxis用法详解
2019/11/04 Python
Python 动态变量名定义与调用方法
2020/02/09 Python
Python内置函数locals和globals对比
2020/04/28 Python
css3个性化字体_动力节点Java学院整理
2017/07/12 HTML / CSS
安纳塔拉酒店度假村及水疗官方网站:Anantara Hotel
2016/08/25 全球购物
复古斯堪的纳维亚儿童服装:Baby go Retro
2017/09/09 全球购物
CK巴西官方网站:Calvin Klein巴西
2019/07/19 全球购物
JAVA程序设计笔试题面试题一套
2015/07/28 面试题
园林技术个人的自我评价
2014/01/08 职场文书
经营目标管理责任书
2014/07/25 职场文书
小学生安全教育广播稿
2014/10/20 职场文书
技术员岗位职责
2015/02/04 职场文书
幼儿教师三分钟演讲稿
2019/06/21 职场文书
导游词之千岛湖
2019/09/23 职场文书
Mysql数据库中datetime、bigint、timestamp来表示时间选择,谁来存储时间效率最高
2021/08/23 MySQL