「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战」
是什么
class
是 ES6
中的一个语法糖结构,底层依然是基于原型和构造函数。何以见得呢?
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() 复制代码
可以看到,两个实例的打印结果基本一致,都有原型,原型中都有构造函数,而且两种写法的 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()
。
如有任何问题或建议,欢迎留言讨论!👏🏻👏🏻👏🏻