我们之前已经使用 new Function 的方式实现过一些面向对象的构造函数,这个章节我们将学习 class (类)的语法,它能帮我们更方便地实现面向对象的编程。

class 的语法

以下我们使用 new Function 的方式实现的一个构造函数, 并用其创建了一个对象实例。

$$jsdemo$$
$$edit$$
function Cat(name) {
    this.family = "猫"

    this.name = name
}

Cat.prototype.sayHello = function () {
    alert(`我叫${this.name},${this.family}科动物。`)
}

const cat = new Cat("加菲猫")
cat.sayHello() // 我叫加菲猫,猫科动物。

我们可以使用 class 的语法来改写, class 的语法如下。

// class 语法
class ClassName {
    // 字段
    field1
    field2
    // 构造函数
    constructor() { ... }
    // 方法
    method1() { ... }
    method2() { ... }
    method3() { ... }
}

constructorclass 的构造方法,每次实例化时就会调用,一个类只能有一个 constructor

$$tip

类名一般使用大写开头的驼峰命名法。

$$

使用 class 改写后的代码如下。

$$jsdemo$$
$$edit$$
class Cat {
    family = "猫"

    constructor(name) {
        this.name = name
    }

    sayHello() {
        alert(`我叫${this.name},${this.family}科动物。`)
    }
}

const cat = new Cat("加菲猫")
cat.sayHello() // 我叫加菲猫,猫科动物。

$$tip

类中也可以定义 getter/setter 访问器。

$$

$$jsdemo$$
$$edit$$
class Cat {
    family = "猫"

    constructor(name) {
        this.name = name
    }

    get hello() {
        return `我叫${this.name},${this.family}科动物。`
    }
}

const cat = new Cat("加菲猫")
alert(cat.hello) // 我叫加菲猫,猫科动物。

$$tip

class 中的代码会自动启用严格模式

$$

$$tip

如果直接 console.log 一个类,在控制台无法展开查看其属性,这时可以用 console.dir

image

$$

class 做了什么?

通过以下的代码,我们发现 class 本质就是定义了一个函数。

$$jsdemo$$
$$edit$$
class Cat {
    family = "猫"

    constructor(name) {
        this.name = name
    }

    sayHello() {
        alert(`我叫${this.name},${this.family}科动物。`)
    }
}

alert(typeof Cat) // function
alert(Cat instanceof Function) // true

const cat = new Cat("加菲猫")
// Cat.prototype 同样被设置为 cat.[[prototype]]
alert(cat.__proto__ === Cat.prototype) // true

我们打印 functionclass 实例的对象,发现它们“几乎一模一样”。

$$jsdemo$$
$$edit$$
function CatFunc(name) {
    this.family = "猫"

    this.name = name
}

CatFunc.prototype.sayHello = function () {
    alert(`我叫${this.name},${this.family}科动物。`)
}

class CatClass {
    family = "猫"

    constructor(name) {
        this.name = name
    }

    sayHello() {
        alert(`我叫${this.name},${this.family}科动物。`)
    }
}

const catFunc = new CatFunc("函数猫")
const catClass = new CatClass("类猫")

console.log(catFunc)
console.log(catClass)

image $$tip

实际上 class 还是做了不少额外的工作的,不仅是一个函数,这些我们将在之后学习到。

$$


练习

  1. 补全以下类的定义,使得代码能正确运行。
class MathArray {
    // 补全代码
}

const arr = new MathArray(5, -10, 20, 12)

alert(arr.max) // 20
alert(arr.min) // -10
alert(arr.sum) // 27

$$answer

$$jsdemo$$
$$edit$$
class MathArray {
    constructor(...args) {
        this.arr = args
    }

    get max() {
        return this.arr.reduce((a, b) => (a > b ? a : b))
    }

    get min() {
        return this.arr.reduce((a, b) => (a < b ? a : b))
    }

    get sum() {
        return this.arr.reduce((a, b) => a + b)
    }
}

const arr = new MathArray(5, -10, 20, 12)

alert(arr.max) // 20
alert(arr.min) // -10
alert(arr.sum) // 27

$$