几个简单的例子学会 ES6 class

1,028 阅读2分钟

「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战

是什么

classES6 中的一个语法糖结构,底层依然是基于原型和构造函数。何以见得呢?

function Person1(name, age) {
  this.name = name
  this.age = age
}
Person1.prototype.say = function () {
  console.log(`My name is ${this.name},i am ${this.age} years old.`)
}

class Person2 {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  say() {
    console.log(`My name is ${this.name},i am ${this.age} years old.`)
  }
}

const xiaoming = new Person1('小明', 18),
  xiaohong = new Person2('小红', 20)
console.dir(xiaoming)
xiaoming.say()
console.dir(xiaohong)
xiaohong.say()

class是构造函数的语法糖.png

可以看到,两个实例的打印结果基本一致,都有原型,原型中都有构造函数,而且两种写法的 say 都是保存在构造函数的原型上。 而且两者都用 new 操作符进行实例化。
而且此时打印 typeof Person2 的结果是 function。😏

基本使用

class Person {
  constructor(name = 'person', age = 18) {
    this.name = name
    this.age = age
  }
  say() {
    console.log(`My name is ${this.name},i am ${this.age} years old.`)
  }
}

const person = new Person(),
  xiaoming = new Person('小明', 20)
console.dir(person)
person.say()
console.dir(xiaoming)
xiaoming.say()

可以看到,使用 new 操作符实例化 Person 类的时候传入的参数会被 constructor 接收并使用,如果不需要传入参数,()可以不写。

static 静态类

假如我们有这样一个场景,要批量生成学生实例,我们可以这样编写 class 类:

class Student {
  constructor(name, age) {
    this.name = name
    this.age = age
    this.school = 'JavaScript 小学'
  }
  say() {
    console.log(`My name is ${this.name},i am ${this.age} years old,my school is ${this.school}.`)
  }
}
const xiaoming = new Student('小明', 18)
xiaoming.say() // My name is 小明,i am 18 years old,my school is JavaScript 小学.

但是这样做有一个问题就是 school 是统一的,没有必要在每个实例上保存,造成内存浪费,也不利于维护。
这个时候我们就可以改写代码如下:

class Student {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  static school = 'JavaScript 小学'
  say() {
    console.log(this)
    console.log(`My name is ${this.name},i am ${this.age} years old,my school is ${Student.school}.`)
  }
}
const xiaoming = new Student('小明', 18)
xiaoming.say() // My name is 小明,i am 18 years old,my school is JavaScript 小学.

static 的作用在于: 如果不添加 static,则属性会被保存在实例上,方法保存在类的原型对象上。
添加 static 后,定义的属性和方法都会绑定在 class 类 上的,所以我们可以通过 Student.school 获取和修改 school 的值。

继承

假设我们的学生中有一些同学是短跑运动员,则他们会有相应的技能。
这个时候我们定义运动员类,而运动员同时又是学生,这个时候就可以让运动员类继承学生类,得到学生相应的属性和方法,同时在运动员类中添加运动员应有的属性和方法。
这个时候我们可以改写代码如下:

class Student {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  static school = 'JavaScript 小学'
  say() {
    console.log(`My name is ${this.name},i am ${this.age} years old,my school is ${Student.school}.`)
  }
}
// 使用 extends 关键字继承父类
class Athlete extends Student {
  constructor(name, age) {
    // 调用父类的 constructor
    super(name, age)
  }
  run() {
    console.log(`I am ${this.name},i am running fast!`)
  }
}
const xiaoming = new Athlete('小明', 18)
xiaoming.say() // My name is 小明,i am 18 years old,my school is JavaScript 小学.
xiaoming.run() // I am 小明,i am running fast!

这里要注意的是 super 不能脱离 extends 单独使用,但是子类中可以不调用 super()
还要注意的是不能在 super() 之前使用 this,也就是如果子类要使用 this,则必须调用 super()

如有任何问题或建议,欢迎留言讨论!👏🏻👏🏻👏🏻