es6之class类
- 一、什么是类
- 二、类的基本用法
- 1.定义类
- 2.constructor() 方法
- 3.静态方法(属性)
- 4.私有方法(属性)
- 三、继承
一、什么是类
类是用于创建对象的模板,类只是让对象原型的写法更加清晰、更像面向对象编程的语法。
class Person {
// 构造函数
constructor(name, age) {
this.name = name
this.age = age
}
// 方法
say(){
console.log('我能说话')
}
}
// 实例化
let zs = new Person('张三', 24)
// 实例化
let ls = new Person('李四', 24)
console.log(zs)
console.log(ls)
二、类的基本用法
1.定义类
类是“特殊的函数”,就像定义的函数表达式和函数声明一样,类语法有两个组成部分:类表达式和类声明。
// 类声明
class Point {
constructor() {
}
}
// 类表达式
let Point = {
constructor(){
}
}
函数声明和类声明之间的一个重要区别,函数声明会提升,类声明不会。需要先声明类,然后再访问它。
// 构造函数会变量提升
let son = new Person('zs', 24)
// Person {name: 'zs', age: 24}
// 类不会变量提升,导致引用异常
let classSon = new ClassPerson('classZs', 48)
// Uncaught ReferenceError: Cannot access 'ClassPerson' before initialization
// 构造函数
function Person(name, age) {
this.name = name
this.age = age
}
// 类
class ClassPerson {
constructor(name, age) {
this.name = name
this.age = age
}
}
2.constructor() 方法
一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加。
class Point {
}
// 等同于
class Point {
constructor() {}
}
constructor()方法什么时候被执行呢?在实例化的时候会自动调用该方法。constructor()方法默认返回实例对象(this)
class Point {
constructor() {
// 通过new命令生成对象实例时,会执行constructor方法
console.log('我执行了')
// 返回的this是实例对象
console.log(this)
}
}
let p = new Point()
类的实例化一定要使用new,否则会报错。这也是跟构造函数的一个主要区别。
// 构造函数
function Point1() {
}
// 可以不使用new,当成普通函数执行
let p1 = Point1()
// 类
class Point {
constructor() {
console.log('我执行了')
console.log(this)
}
}
// 类不使用new会报错
// Uncaught TypeError: Class constructor Point cannot be invoked without 'new'
let p = Point()
3.静态方法(属性)
类相当于实例的原型,所有在类中定义的方法(属性),都会被实例继承。如果在一个方法(属性)前,加上static关键字,就表示该方法(属性)不会被实例继承,而是直接通过类来调用。
class Person {
static personAge = 28
constructor(name, age) {
this.name = name
this.age = age
}
static getAge(age) {
return this.personAge + age
}
}
let zs = new Person('zs', 28)
// 静态属性只能通过类来访问
console.log(Person.personAge) // 28
// 静态属性实例不能使用
console.log(zs.personAge) // undefined
// 静态方法只能通过类来访问
Person.getAge(28)
// 静态方法实例不能使用
// zs.getAge();
// Uncaught TypeError: zs.getAge is not a function
// 执行会报错,因为this在严格模式下是underfined
// 这个方法提取出来单独使用,this会指向该方法运行时所在的环境(由于 class 内部是严格模式,所以 this 实际指向的是undefined),从而导致找不到getAge方法而报错。
let getAge = Person.getAge
getAge(18)
// Uncaught TypeError: Cannot read properties of undefined (reading 'personAge')
尽管静态方法(属性)不能被实例使用,但是父类的静态方法,可以被子类继承(继承那边会介绍)。
4.私有方法(属性)
私有方法(属性),是只能在类的内部访问的方法和属性,外部不能访问。这也是比较常见的需求,有利于代码的封装。 然而私有方法(属性)的定义之前一直不是很友好,在ES2022正式为class添加了私有属性,方法是在属性名之前使用#表示。
class Person {
// 私有属性
#name = '我能说话了'
// 私有方法
#say() {
// 引用私有属性
console.log(this.#name)
}
// 可能这样间接调用私有方法
indirectSay() {
console.log(this) //Person
this.#say()
}
}
let p = new Person()
// p.#name
// 报错 Uncaught SyntaxError: Private field '#name' must be declared in an enclosing class
// p.#say()
// 报错 Uncaught SyntaxError: Private field '#say' must be declared in an enclosing class
// 间接调用
p.indirectSay()
// 我能说话了
当然,如果在私有方法(属性)前面加上static关键字,表示这是一个静态的私有方法(属性)。
三、继承
类可以通过extends关键字实现继承,让子类继承父类的属性和方法。
ES6 规定,子类必须在constructor()方法中调用super(),否则就会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。如果不调用super()方法,子类就得不到自己的this对象。