详解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----文件操作
Jan 18 Javascript
JavaScript 面向对象之命名空间
May 04 Javascript
如何使用json在前后台进行数据传输实例介绍
Apr 11 Javascript
图片轮换效果实现代码(点击按钮停止执行)
Apr 12 Javascript
jQuery多个input求和的实现方法
Feb 12 Javascript
学习JavaScript设计模式之责任链模式
Jan 18 Javascript
jQuery对象的链式操作用法分析
May 10 Javascript
js addDqmForPP给标签内属性值加上双引号的函数
Dec 24 Javascript
jquery mobile移动端幻灯片滑动切换效果
Apr 15 Javascript
JavaScript中如何判断一个值的类型
Sep 15 Javascript
vue项目中监听手机物理返回键的实现
Jan 18 Javascript
比较node.js和Deno
Apr 27 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/03/10 PHP
php 网页播放器用来播放在线视频的代码(自动判断并选择视频文件类型)
2010/06/03 PHP
PHP中IP地址与整型数字互相转换详解
2014/08/20 PHP
php操作redis缓存方法分享
2015/06/03 PHP
PHP实现在线阅读PDF文件的方法
2015/06/17 PHP
Centos6.5和Centos7 php环境搭建方法
2016/05/27 PHP
javascript 添加和移除函数的通用方法
2009/10/20 Javascript
js返回上一页并刷新代码整理
2012/12/21 Javascript
js 高效去除数组重复元素示例代码
2013/12/19 Javascript
Boostrap基础教程之JavaScript插件篇
2016/09/08 Javascript
[49:08]FNATIC vs Infamous 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
Python XML RPC服务器端和客户端实例
2014/11/22 Python
Python的SQLAlchemy框架使用入门
2015/04/29 Python
判断python字典中key是否存在的两种方法
2018/08/10 Python
Flask Web开发入门之文件上传(八)
2018/08/17 Python
如何利用python发送邮件
2020/09/26 Python
如何完美的建立一个python项目
2020/10/09 Python
python 如何停止一个死循环的线程
2020/11/24 Python
CSS3盒子模型详解
2013/04/24 HTML / CSS
NEW LOOK官网:英国时装零售巨头之一,快时尚品牌
2017/01/11 全球购物
JACK & JONES瑞典官方网站:杰克琼斯欧式风格男装
2017/12/23 全球购物
MSC邮轮官方网站:加勒比海、地中海和世界各地的假期
2018/08/27 全球购物
Volcom英国官方商店:美国殿堂级滑板、冲浪、滑雪服装品牌
2019/03/13 全球购物
LN-CC英国:伦敦时尚生活的缩影
2019/09/01 全球购物
罗马尼亚在线杂货店:Pilulka.ro
2019/09/28 全球购物
完美实现CSS垂直居中的11种方法
2021/03/27 HTML / CSS
会计实习生自我鉴定
2013/12/12 职场文书
工作态度检讨书
2014/02/11 职场文书
就业协议书的作用
2014/04/11 职场文书
公务员诚信承诺书
2014/05/26 职场文书
优秀会计求职信
2014/07/04 职场文书
四风专项整治工作情况汇报
2014/10/28 职场文书
秋收起义观后感
2015/06/11 职场文书
大学校园招聘会感想
2015/08/10 职场文书
学习习近平主席讲话心得体会
2016/01/20 职场文书
go语言中fallthrough的用法说明
2021/05/06 Golang