陌上寒

陌上寒个人博客

javascript面向对象之ES6中的类和继承

很多人反应前两天的内容抽象难懂并且不实用,这是广大前端的共同心声,所以ES6对继承做了优化
本文部分内容参考《ES6标准入门》(第二版)
通过构造函数声明类(其中部分代码使用了es6,但依然是传统的思想)

    function HeroES5(name, skill) {
      this.name = name
      this.skill = skill
    }
    HeroES5.prototype.doSth = function () {
      console.log(`练习${this.skill}`);
    }
    HeroES5.prototype.sayName = function () {
      console.log(`我的名字是${this.name}`);
    }

class

在ES6中引入了class(类)的概念,ES6中的class可以看做是一个语法糖,他的绝大部分功能ES5都可以做到,新的class写法是对象原型的写法更加清晰,更像面向对象编程的写法,将上面的demo用ES6来写

    class HeroES6 {
      constructor(name, skill) {
        this.name = name
        this.skill = skill
      }
      doSth() {
        console.log(`练习${this.skill}`);
      }
      sayName() {
        console.log(`我的名字是${this.name}`);
      }
    }

我们分别观察一下他们的数据类型

    console.log(typeof HeroES5);//=>function
    console.log(typeof HeroES6);//=>function

看来ES6中的class也是函数类型,既然是函数类型就一定有prototype
我们分别观察一下他们的prototype

    console.log(HeroES5.prototype);
    console.log(HeroES6.prototype);

《javascript面向对象之ES6中的类和继承》

构造函数中的prototype属性在ES6的“类”上继续存在,事实上,类的所有方法都定义在类的prototype属性上

我们通过类实例化一个对象

   const hr = new HeroES6("黄蓉", "打狗棒")
    console.log(hr);

《javascript面向对象之ES6中的类和继承》
上面的栗子中,name和skill是hr的自身属性,(因为定义在this变量上),doSth()和sayName(),是原型对象上的属性,(因为定义在HeroES6类上)
还记得hasOwnProperty吗?回忆一下关于javascript的Object. hasOwnProperty,看我就够了
Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。

    console.log(hr.hasOwnProperty('name')); //=>true
    console.log(hr.hasOwnProperty('skill')); //=>true
    console.log(hr.hasOwnProperty('doSth')); //=>false
    console.log(hr.hasOwnProperty('sayName')); //=>false

好,关于ES6中的class我们就说这么多,还有很多没有提及的,可以参考这个链接

class的继承

如果ES5的继承让你头晕目眩,那么是时候研究一下ES6的继承了
Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
举一个

//定义一个类
    class HeroES6 {
      constructor(name, skill) {
        this.name = name
        this.skill = skill
      }
      doSth() {
        return `练习${this.skill}`
      }
      sayName() {
        return `我的名字是${this.name}`
      }
    }
//定义一个类,继承了  HeroES6类  
    class Gj extends HeroES6 {
      constructor(name, skill,favourite) {
        super(name, skill, favourite)// 调用父类的 constructor(name, skill) 
        this.favourite = favourite
      }
      doSth() {
        return super.doSth() + this.favourite//调用父类的sayName() 
      }
    }

    const gj = new Gj('郭靖','降龙十八掌','吃饭')
    console.log(gj);
    console.log(gj.doSth())//=>练习降龙十八掌吃饭
    console.log(gj.sayName());//=>我的名字是郭靖

输出
《javascript面向对象之ES6中的类和继承》
我们先定义一个类HeroES6,我们可以称它为父类,
我们又定义了一个Gj类,我们可以称它为子类,该类通过extends关键字,继承了HeroES6类的所有属性和方法

子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

如果子类没有定义constructor方法,这个方法会被默认添加,如果手动添加了constructor方法,就一定要调用super方法,否则新建实例时会报错,调用了super后才能使用this关键字

//部分代码省略
  class Gj extends HeroES6 {
      constructor(name, skill, favourite) {
        this.favourite = favourite//不能在super前调用this
        super(name, skill, favourite)
      }
      doSth() {
        return super.doSth() + this.favourite
      }
    }
//部分代码省略

输出
《javascript面向对象之ES6中的类和继承》

super

关于super阮一峰的ES6说的很详细
我们强调一点
super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。
子类Gj的构造函数之中的super(),代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。
注意,super虽然代表了父类 HeroES6的构造函数,但是返回的是子类Gj的实例,即super内部的this指的是Gj
ES6的继承使用方法地区简单方便

好了,关于javascript的继承就介绍到这里

  1. 杰克说道:

    写的不错,保持谦虚,继续努力。继承还是比较重要的。

发表评论

电子邮件地址不会被公开。 必填项已用*标注