class 类
在 JavaScript 中,class 是一种创建对象的模板。使用 class 关键字可以方便地创建类,而不需要使用传统的构造函数和原型链。类包含属性和方法,可以实例化创建对象,这些对象可以继承父类的属性和方法。
以下是一些使用类的场景:
- 组件化开发:类是组件化开发的基础。通过定义一个类,我们可以方便地创建多个具有相同属性和方法的对象,从而实现组件化开发的目标。
class MyComponent {
constructor(props) {
this.props = props
this.state = { count: 0 }
}
// 生命周期方法
componentDidMount() {
console.log("Component mounted")
}
// 事件处理方法
handleClick() {
this.setState({ count: this.state.count + 1 })
}
// 渲染方法
render() {
return `
<div>
<p>Count: ${this.state.count}</p>
<button onclick="(${this.handleClick.bind(this)})()">Click me</button>
</div>
`
}
}
const container = document.getElementById("container")
const myComponent = new MyComponent({ name: "My Component" })
container.innerHTML = myComponent.render()
myComponent.componentDidMount() // 执行生命周期方法
在上面的示例中,我们定义了一个 MyComponent 类来实现组件化开发。它接收一个 props 对象作为参数,其中包含组件所需要的属性。在 constructor 方法中,我们将 props 对象和组件的状态(state)保存在实例中。
接下来,我们定义了组件的生命周期方法 componentDidMount、事件处理方法 handleClick 和渲染方法 render。componentDidMount 方法在组件挂载到 DOM 上后执行,可以用来执行一些初始化操作。handleClick 方法用于处理组件的点击事件。render 方法返回组件的 HTML 模板。
最后,我们创建了一个 MyComponent 实例,并将其渲染到页面上。我们还调用了 componentDidMount 方法来执行生命周期方法。
使用 class 实现组件化开发可以使代码更加结构化、可维护性更高。同时,它也提供了许多方便的特性,如生命周期方法、状态管理等,使开发者能够更加轻松地构建复杂的应用程序。
- 封装和抽象:类可以封装和抽象对象的特性和行为,通过公开接口,我们可以使用对象的属性和方法,而不需要知道内部实现的细节。
class Task {
constructor(name, priority, date) {
this.name = name
this.priority = priority
this.date = date
}
// 根据优先级返回任务的类别
getCategory() {
if (this.priority > 5) {
return "高"
} else if (this.priority > 3) {
return "中"
} else {
return "低"
}
}
// 根据任务完成时间返回类别
getTimeCategory() {
let today = new Date()
let taskDate = new Date(this.date)
let diff = (taskDate - today) / (1000 * 60 * 60 * 24)
if (diff < 0) {
return "已过期"
} else if (diff < 1) {
return "今天"
} else if (diff < 7) {
return "一周内"
} else {
return "一周后"
}
}
// 生成任务列表的 HTML
getHtml() {
let html = `
<div class="task">
<div class="name">${this.name}</div>
<div class="category">${this.getCategory()}</div>
<div class="time-category">${this.getTimeCategory()}</div>
<div class="date">${this.date}</div>
</div>
`
return html
}
}
// 任务列表类
class TaskList {
constructor() {
this.tasks = []
}
// 添加任务
addTask(name, priority, date) {
let task = new Task(name, priority, date)
this.tasks.push(task)
}
// 生成任务列表的 HTML
getHtml() {
let html = ""
for (let task of this.tasks) {
html += task.getHtml()
}
return html
}
}
上面的代码定义了一个 Task 类和一个 TaskList 类,Task 类用来表示一个任务,TaskList 类用来管理任务列表。Task 类包括了一些任务的基本属性,如名称、优先级和截止日期,以及一些方法,如 getCategory()、getTimeCategory() 和 getHtml(),用来生成任务的类别、完成时间类别和 HTML 代码。TaskList 类包括了一个 tasks 数组和两个方法,addTask() 和 getHtml(),用来添加任务和生成任务列表的 HTML 代码。
let taskList = new TaskList()
taskList.addTask("写作业", 1, "2023-04-30")
taskList.addTask("做项目", 7, "2023-05-10")
taskList.addTask("看电影", 4, "2023-05-15")
document.querySelector("#task-list").innerHTML = taskList.getHtml()
- 继承:类可以通过继承,从父类继承属性和方法,并添加自己的特性和行为,从而实现代码复用和扩展。
// 定义父类
class Task {
constructor(title, priority) {
this.title = title
this.priority = priority
this.isCompleted = false
}
complete() {
console.log(`完成任务:${this.title}`)
this.isCompleted = true
}
}
// 定义子类
class ScheduledTask extends Task {
constructor(title, priority, deadline) {
super(title, priority)
this.deadline = deadline
}
isUrgent() {
const today = new Date()
return today > this.deadline
}
print() {
console.log(`[${this.priority}] ${this.title} (${this.deadline})`)
}
}
// 使用示例
const task1 = new ScheduledTask("任务1", 1, new Date("2023-05-01"))
const task2 = new ScheduledTask("任务2", 2, new Date("2023-06-01"))
task1.complete() // 输出:完成任务:任务1
console.log(task1.isUrgent()) // 输出:true
task2.print() // 输出:[2] 任务2 (Tue Jun 01 2023 00:00:00 GMT+0800 (中国标准时间))
这里定义了一个 Task 父类和一个 ScheduledTask 子类,子类继承了父类的属性和方法,并添加了自己的属性和方法。
子类可以使用 super 调用父类的构造函数,并传入对应的参数。在子类中可以定义自己的方法,也可以重写父类的方法。
使用时,可以创建子类的实例,并调用继承的方法或子类自己的方法。同时也可以访问继承的属性或子类新增的属性。
- 多态:类可以使用多态的特性,即子类可以重写父类的方法,从而实现不同对象对同一方法的不同实现。
class Task {
constructor(name, priority) {
this.name = name
this.priority = priority
}
execute() {
console.log(`执行任务 ${this.name}`)
}
}
class UrgentTask extends Task {
execute() {
console.log(`紧急任务 ${this.name} 正在执行`)
}
}
class DailyTask extends Task {
execute() {
console.log(`日常任务 ${this.name} 正在执行`)
}
}
let taskList = [new UrgentTask("清理垃圾", 1), new DailyTask("洗碗", 2), new UrgentTask("开会", 3)]
taskList.forEach((task) => task.execute())
上面的代码中,Task 是基类,它有一个 execute() 方法,用于执行任务。UrgentTask 和 DailyTask 是 Task 的子类,它们都继承了 execute() 方法,并分别实现了不同的行为。
在主程序中,我们创建了一个任务列表,并使用 forEach() 方法遍历该列表,对每个任务执行 execute() 方法。由于每个任务都是 Task 的子类,所以它们都实现了 execute() 方法,但是具体的行为却各不相同,这就体现了类的多态性。
- 模块化开发:类也可以用于模块化开发,将一组相关的方法和属性封装在一个类中,从而方便使用和维护。同时,类的实例化也可以实现对不同模块的访问和调用。
// 定义一个类作为模块
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
sayHello() {
console.log(`Hello, my name is ${this.name}, I am ${this.age} years old.`)
}
}
// 导出模块
export default Person
// 导入模块
import Person from "./Person.js"
// 使用模块
const person = new Person("Tom", 20)
person.sayHello()