详解JavaScript之ES5的继承

自从有了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的继承的资料请关注我们其它相关文章!

(0)

相关推荐

  • JavaScript ES5标准中新增的Array方法

    ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块,我们可能就不需要去有板有眼地for循环了. ES5中新增了写数组方法,如下: forEach (js v1.6) map (js v1.6) filter (js v1.6) some (js v1.6) every (js v1.6) indexOf (js v1.6) lastIndexOf (js v1.6) reduce (js v1.8) reduceRight (js v1.8) 1.js中常用的数

  • js定义类的方法示例【ES5与ES6】

    本文实例讲述了js定义类的方法.分享给大家供大家参考,具体如下: 以下是es5标准里定义类的方法: <script> function Point(x,y){ this.x=x; this.y=y; } Point.prototype.toString=function(){ return '('+this.x+', '+this.y+')'; } var point=new Point(1,2); console.log(point); </script> 运行结果: 上面这样用

  • 详解vue-cli+es6引入es5写的js(两种方法)

    学习了vue有一段日子了,vue+es6开发非常好用,vue的插件非常多,很充足,但是还是会用到引入第三方外部js的时候,但是很多人在vue-cli中的.vue文件引入es6会出很多错误,因为我们的代码是es6写的,你引入es5的js当然会出问题,那么而接下来我讲大家讲解一波,怎么引入第三方es5写的 js 方法1: import XX from "路径" Vue.use(XX); 这里的js文件要导出 用export default { Vue.proprtypes.aa=funct

  • js es6系列教程 - 基于new.target属性与es5改造es6的类语法

    es5的构造函数前面如果不用new调用,this指向window,对象的属性就得不到值了,所以以前我们都要在构造函数中通过判断this是否使用了new关键字来确保普通的函数调用方式都能让对象复制到属性 function Person( uName ){ if ( this instanceof Person ) { this.userName = uName; }else { return new Person( uName ); } } Person.prototype.showUserNam

  • JS实现集合的交集、补集、差集、去重运算示例【ES5与ES6写法】

    本文实例讲述了JS实现集合的交集.补集.差集.去重运算.分享给大家供大家参考,具体如下: ES5写法: ///集合取交集 Array.intersect = function () { var result = new Array(); var obj = {}; for (var i = 0; i < arguments.length; i++) { for (var j = 0; j < arguments[i].length; j++) { var str = arguments[i][

  • JavaScript设计模式之原型模式分析【ES5与ES6】

    本文实例讲述了JavaScript设计模式之原型模式.分享给大家供大家参考,具体如下: 从设计模式的角度讲,原型模式是用于创建对象的一种模式,若需要创建一个对象,一种方法是先指定其类型,然后通过类来创建这个对象,另一种方法是通过原型来创建,不必关心对象的具体类型,而是找到一个对象,然后通过克隆来创建一个一模一样的对象. ES5提供了Object.create(obj)方法来克隆对象,在不支持Object.create(obj)方法的浏览器中,可以使用以下代码: Object.create = O

  • 详解JavaScript之ES5的继承

    自从有了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

  • 详解JavaScript基于面向对象之继承实例

    javascript面向对象继承的简单实例: 作为一门面向对象的语言,继承自然是它的一大特性,尽管javascript的面向对象的实现机制和和c#和java这样典型的面向对象不同,但是继承的基本特点还是具有的,简单的说就是获得父级的方法和属性,下面是一段简单的实例,大家有兴趣可以分析一下: window.onload = function(){ function parent(age,name){ this.age = age; this.name = name; } parent.protot

  • 详解JavaScript基于面向对象之继承

    一.面相对象继承机制       这个实例使用UML很好的解释了继承机制.       说明继承机制最简单的方式是,利用一个经典的例子就是几何形状.实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边).圆是椭圆的一种,它只有一个焦点.三角形.矩形和五边形都是多边形的一种,具有不同数量的边.正方形是矩形的一种,所有的边等长.这就构成了一种完美的继承关系,很好的解释了面向对象的继承机制.        在这个例子中,形状是椭圆形和多边形的基类(通常我们也可以叫它父类,所有类都由

  • 详解Javascript中prototype属性(推荐)

    在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不是基于'类的',而是通过构造函数(constructor)和原型链(prototype chains)实现的.但是在ES6中提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类.基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能

  • js对象实例详解(JavaScript对象深度剖析,深度理解js对象)

    这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕. 平时发的文章基本都是开发中遇到的问题和对最佳解决方案的探讨,终于忍不住要写一篇基础概念类的文章了. 本文探讨以下问题,在座的朋友各取所需,欢迎批评指正: 1.创建对象 2.__proto__与prototype 3.继承与原型链 4.对象的深度克隆 5.一些Object的方法与需要注意的点 6.ES6新增特性 下面反复提到实例对象和原型对象,通过构造函数 new

  • 详解JavaScript的this指向和绑定

    注意: 本文属于基础篇,请大神绕路.如果你不够了解,或者了解的还不完整,那么可以通过本文来复习一下. this 指向的类型 刚开始学习 JavaScript 的时候,this 总是最能让人迷惑,下面我们一起看一下在 JavaScript 中应该如何确定 this 的指向. this 是在函数被调用时确定的,它的指向完全取决于函数调用的地方,而不是它被声明的地方(除箭头函数外).当一个函数被调用时,会创建一个执行上下文,它包含函数在哪里被调用(调用栈).函数的调用方式.传入的参数等信息,this

  • 详解Javascript 中的 class、构造函数、工厂函数

    到了ES6时代,我们创建对象的手段又增加了,在不同的场景下我们可以选择不同的方法来建立.现在就主要有三种方法来构建对象,class关键字,构造函数,工厂函数.他们都是创建对象的手段,但是却又有不同的地方,平时开发时,也需要针对这不同来选择. 首先我们来看一下,这三种方法是怎样的 // class 关键字,ES6新特性 class ClassCar { drive () { console.log('Vroom!'); } } const car1 = new ClassCar(); consol

  • 详解JavaScript原型与原型链

    正如一些面向对象语言中所实现的那样,在JavaScript中我们有时也需要创建一个拥有公共函数与属性的类作为父类来减少代码重复.实现类型检查与实现更加清晰地代码结构.在JavaScript中,继承是通过原型链实现的.了解JavaScript的继承与原型链之前首先需要了解JavaScript中对象创建的方式. 在JavaScript中创建对象 JavaScript中对象创建的方式有两种:工厂方法(Factory Functions).构造器方法(Constructor Functions) . 工

  • 详解JavaScript中的链式调用

    链模式 链模式是一种链式调用的方式,准确来说不属于通常定义的设计模式范畴,但链式调用是一种非常有用的代码构建技巧. 描述 链式调用在JavaScript语言中很常见,如jQuery.Promise等,都是使用的链式调用,当我们在调用同一对象多次其属性或方法的时候,我们需要多次书写对象进行.或()操作,链式调用是一种简化此过程的一种编码方式,使代码简洁.易读. 链式调用通常有以下几种实现方式,但是本质上相似,都是通过返回对象供之后进行调用. this的作用域链,jQuery的实现方式,通常链式调用

  • 详解JavaScript中new操作符的解析和实现

    前言 new 运算符是我们在用构造函数创建实例的时候使用的,本文来说一下 new 运算符的执行过程和如何自己实现一个类似 new 运算符的函数. new 运算符的运行过程 new 运算符的主要目的就是为我们创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例(比如箭头函数就没有构造函数,所以是不能 new 的).new 操作符的执行大概有以下几个步骤: 创建一个新的空对象 把新对象的 __proto__ 链接到构造函数的 prototype 对象(每一个用户定义函数都有一个 proto

随机推荐