目录
- class
- 构造函数
- 方法
- 原型方法
- 访问器方法
- 静态方法
- 继承
- super
- minxin
- 关于多态
class
在ES6中之前如果我们想实现类只能通过原型链和构造函数的形式,不仅难以理解步骤也十分繁琐
在ES6中推出了class关键字,它可以在js中定一个类,通过new来实例化这个类的对象
需要注意的是class关键字只是一个语法糖,它的本质还是通过原型链和构造函数来实现的
class中的代码默认都是运行在strict模式下的
以下是一个简单的class关键字用法
class Person {name = "zhangsan";
}
let people = new Person();
let Person2 = class {name = "lisi";
};
let people2 = new Person2();
console.log(people, people2);

可以看到类有两个定义方法,一个是类声明,即class 类名,还有一个是类表达式,类表达式可以命名也可以不命名,即 var/let/const 局部名称 = class [类名] {}
无论是类声明还是类表达式都不会提升,想要使用类就必须在类定义的后面
这种定义在class中的属性被称为公有字段,如果在字段前加上#就成了私有字段
构造函数
如果我们希望在构造对象的时候传入一些参数就需要修改这个类的构造函数constructor
class Person {constructor(name, age, address) {this.name = namethis.age = agethis.address = address}
}
let people = new Person("zhangsan", 18, "wuhan")
console.log(people)

构造函数的名称确定为constructor,如果一个类中含有多个constructor则会抛出一个错误
方法
原型方法
能被多个实例共享的方法
class Person {constructor(name, age, address) {this.name = namethis.age = agethis.address = address}eating() {console.log(this.name + "eating...")}running() {console.log(this.name + " running...")}
}
let people = new Person("zhangsan", 18, "wuhan")
console.log(people)
people.running()
people.running()

访问器方法
我们可以针对对应的属性设置get和set来拦截原本的修改和读取操作
class Person {constructor(name, age, address) {this._name = namethis.age = agethis.address = address}get name() {console.log("执行了读取操作")return this._name}set name(newName) {console.log("执行了设置操作")this._name = newName}
}
let people = new Person("zhangsan", 18, "wuhan")
console.log(people.name)
people.name = "lisi"

注意,如果get或set与属性名重复的话就会发生死循环
静态方法
静态方法则是指直接由类来调用的方法,不需要实例,通过static来定义静态方法
class Person {constructor(name, age, address) {this.name = namethis.age = agethis.address = address}static birth(name, age, address) {return new Person(name, age, address)}
}
let people = Person.birth("wangwu", 0, "wuhan")
console.log(people)

继承
在ES6之前我们想要实现继承是十分麻烦且繁琐的,如何在ES6之前实现继承可以看我这篇文章
js原型与原型链
而在ES6中有了新的关键字extends可以更方便的实现继承
class Person {constructor(name, age, address) {this.name = namethis.age = agethis.address = address}
}
class Man extends Person {
}
super
super关键字可以访问父类的方法与属性
需要注意的是在constructor中调用super前不能使用this
为什么在调用super前不能访问this可以看我这篇文章
未动笔,未来可寄
super.prop可以访问父类的静态属性与方法
class Person {constructor(name, age, address) {this.name = namethis.age = agethis.address = address}eating() {console.log(this.name + "eating...")}
}
class Man extends Person {constructor(...args) {super(...args)}eating() {super.eating()}
}
let people = new Man("zhangsan", 18, "wuhan")
console.log(people)
people.eating()

minxin
因为js的继承只能继承一个类,因为函数的显式原型不可能有多个
如果我们想要让子类有尽可能多的复用其他类就可以使用混入
混入的原理十分简单,假如我们有ABC三个类,我们希望C能继承AB两个类,思路就是我们可以先让B继承A,再让C继承B
我们可以将这个过程封装成一个函数再extends
class Person {constructor(name, age, address) {this.name = namethis.age = agethis.address = address}eating() {console.log(this.name + "eating...")}
}
function minix(BaseClass) {return class extends BaseClass {sleeping() {console.log(this.name + " sleeping...")}}
}
class Man extends minix(Person) {constructor(...args) {super(...args)}eating() {super.eating()}
}
let people = new Man("zhangsan", 18, "wuhan")
console.log(people)
people.eating()
people.sleeping()

关于多态
我觉得js是有多态,多态的概念很简单:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果
就比如a+b,如果传入的是1和2,返回的自然是3,如果传入的是"1"和"2",返回的就是"12"
这么一看js也确实符合
多态最常用的实现方式就是重载与重写
重写在原型链上已经实现了不必再说,关键就在于重载,重载指同名但参数不同的方法,但js中方法本身就可以传任意数量任意类型的参数,我们可以通过if来判断不同类型的参数执行什么操作,但这个算不算重载也很难说
我认为js作为一门弱类型的语言天然就应该是具有多态这个特性的