JavaScript编码之路【ES6新特性之Class类】(二)

简介: JavaScript编码之路【ES6新特性之Class类】(二)

JavaScript编码之路【ES6新特性之Class类】(一):https://developer.aliyun.com/article/1556686


二. ES6类的继承

2.1. extends关键字

假设有一种神奇的魔法,它能在父母(Person类)和孩子(Student类)之间架起一座神秘的桥梁。这座桥允许孩子从父母那里获得并流传至子孙的知识(属性)、技能(方法)。这就是ES6为俺们引入的extends关键字【其实在ES5中也是可以实现继承的方案,但是过程却依然是非常繁琐的】:


class Person {

}

class Student extends Person {
  
}

Student类通过extends关键字借由魔法桥从Person类那里继承了特性和能力。


接下来,小菜鸡就把这个故事讲细一点:


每个人都有自己的姓名和年龄,同样地,每个Person实例也有自己的name和age属性。他们可以跑步和吃东西,因此有running和eating方法。


class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }

  running() {
    console.log(this.name + " running~")
  }

  eating() {
    console.log(this.name + " eating~")
  }
}

然后有一种特别的人,他们是学生。他们继承了人的特性,但他们还有自己的特殊之处,比如他们有学生号,所以Student类有自己的sno属性。他们不仅能跑步和吃东西,还需要学习,所以有studying方法。但最神奇的魔法就在于,他们继承了他们的父辈的所有特性和能力。

class Student extends Person {
  constructor(name, age, sno) {
    super(name, age)
    this.sno = sno
  }

  studying() {
    console.log(this.name + " studying~")
  }
}

var stu = new Student("why", 18, 111)

在Student构造函数中,魔法师调用了super函数【下面会详细介绍】。这个super就如同一个魔法传送门,它将孩子带到父母那里,让孩子的属性和父母一样。如果你的类继承了其他类,那么super就必须在this之前被调用,因为它实际上会创建出this【换句话说,super负责创建this,然后你才能对this做赋值操作。这就是为什么在constructor方法中,你必须首先调用super,然后才能使用this关键字。如果你试图在调用super之前使用this,JavaScript会抛出一个引用错误】。


看,我们已经成功创建了一个Student实例,他的名字是why,18岁,学号是111。他能跑步、吃东西,还能学习,因为他继承了Person类,并添加了自己的特性studying。

2.2. super关键字【魔法棒】

这是一段来自 CodeWhy 王元红老师的温馨提示⚡

【注意:在子(派生)类的构造函数中使用this或者返回默认对象之前,必须先通过super调用父类的构造函数!】

super的使用位置有3

  • 子类的构造函数
  • 实例方法
  • 静态方法

想象一下,super关键字是一个拥有神奇力量的魔法棒。一旦你挥舞它,神奇的事情就会发生:你的子类就能像父亲一样,拥有父类的属性和方法。这可真是其非凡之处!

首先,让我们看一下super怎么使用。一般情况下,我们会在子类的构造函数、实例方法、静态方法中找到它。

// 调用 父对象/父类 的构造函数
super([arguments])

// 调用 父对象/父类 上的方法
super.functionOnParent([arguments])

如果你在子类的构造函数中使用this,或者没有调用super就要返回对象,那你将会得到一个错误信息。一定要记得,使用super关键字才会调用父类构造函数并且创建出this。

class Person {

}

class Student extends Person {
  constructor(sno) {
    // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
  }
}

var stu = new Student()

其中,super在实例方法或静态方法中调用父类方法的能力,使我们可以很方便地实现方法的重写。

class Person {
  eating() {
    console.log(this.name + " eating~")
  }

  static create() {
    console.log("Person create")
  }
}

class Student extends Person {
  // 方法的重写
  eating() {
    console.log("做完作业~")
    super.eating()
  }

  static create() {
    super.create()
    console.log("Student create")
  }
}

var stu = new Student()
stu.eating()

Student.create()
--- 控制台 ---
做完作业~
undefined eating~
Person create
Student create

如上为Student类重写了eatingcreate方法。但在新方法中,我们依然调用了Person中的eatingcreate方法。这就好像孩子在观察从父亲那里学到的技能之后,找到自己独特的使用方式。

2.3. 继承内置类

在我们已经知道如何继承自定义的类之后,我们同样也可以选择继承JavaScript内置的类,例如Array。这就像我们有能力把超级英雄的超能力赋予给我们的角色,让他能够飞翔、变身或者制造能量光束。

class HYArray extends Array {
  lastItem() {
    return this[this.length-1]
  }
}

var array = new HYArray(10, 20, 30)
console.log(array.lastItem())

array.filter(item => {
  console.log(item)
})

如上创建了一个新类HYArray,它继承自Array类。这就好像我们的角色继承了超级英雄的能力。在HYArray增加了一个新方法lastItem,能够返回数组的最后一个元素。这么做,咱们的角色除了能做超级英雄能做的事情,还能做一些超级英雄做不到的事情。


同时,咱们可以继续改进HYArray类,令它使用filter方法返回的数组还是原来的Array,而不是HYArray。只需要在HYArray类中添加一个Symbol.species方法而已。这个方法返回该构造函数用来创建派生对象的默认构造函数。

class HYArray extends Array {
  lastItem() {
    return this[this.length-1]
  }

  static get [Symbol.species]() {
    return Array
  }
}

var array = new HYArray(10, 20, 30)
console.log(array.lastItem())

var newArr = array.filter(item => {
  console.log(item)
})

console.log(newArr instanceof HYArray) // false
console.log(newArr instanceof Array) // true

现在HYArray就如同一个超级英雄,他不仅继承了父类的能力,还能够做一些其他超级英雄做不到的事情!

小结

参考代码全部来自 CodeWhy 王元红老师 【来源微信公众号 CodeWhy 】,感谢我的引路人王老师。

目录
相关文章
|
4天前
|
JavaScript 前端开发 网络架构
JavaScript编码之路【对象的增强、ES6新特性之函数的默认值设置 、rest参数 (剩余参数)、拓展运算符、对象与数组的解构赋值】
JavaScript编码之路【对象的增强、ES6新特性之函数的默认值设置 、rest参数 (剩余参数)、拓展运算符、对象与数组的解构赋值】
7 1
|
4天前
|
存储 JavaScript 前端开发
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(二)
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(二)
9 1
|
1天前
|
JavaScript
JS 自测题 —— 手写 class
JS 自测题 —— 手写 class
5 0
|
4天前
|
存储 JavaScript 前端开发
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(一)
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(一)
7 0
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的个人健康管理系统小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的个人健康管理系统小程序附带文章源码部署视频讲解等
8 2
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的高校宿舍信息管理系统小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的高校宿舍信息管理系统小程序附带文章源码部署视频讲解等
7 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的电影交流平台小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的电影交流平台小程序附带文章源码部署视频讲解等
6 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的电器维修系统小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的电器维修系统小程序附带文章源码部署视频讲解等
7 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的大学生校园兼职微信小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的大学生校园兼职微信小程序附带文章源码部署视频讲解等
9 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的二手物品交易平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的二手物品交易平台附带文章源码部署视频讲解等
6 1