面向对象的 JavaScript
问题
在创建动态 Web 应用时,JavaScript 是一个强大的工具,它使我们能够编写函数来操作 DOM 并处理客户端与服务器之间的交互。然而,随着 Web 应用规模的增长,这些函数会迅速交织成复杂的网络结构,从而更容易出现 bug,并且代码通常更难阅读和修改。随着 Web 应用规模的增长,我们很可能需要处理数十个甚至数百个 HTML 元素。反过来,DOM 操作也会很快变得混乱不堪。幸运的是,有一种方法可以改变代码结构,将分散的函数网络转变为组件或单元格的结构或集合。这种组织代码的方式被称为面向对象编程。
面向对象编程:概述:
在面向对象编程中,我们的代码被划分到不同的容器中。这些容器由数据、信息、变量以及我们定义的与这些信息相关的行为组成。面向对象编程赋予代码结构,它建立了数据与定义行为的函数之间的关系。我们以一种方式组织代码:实例化数据,使其继承我们在与其关联的类中定义的行为属性。这种代码组织方式的优点包括:
- 我们的代码更容易修改。添加/删除代码的位置很清晰。
- 我们可以设计代码,使我们定义的行为函数只与它们应该交互的数据进行交互。
- 我们的代码更容易复现。当使用唯一数据创建对象时,我们在类中定义的实例方法会以该对象独有的方式运行。
- 通过增加组织结构,我们的代码更易于阅读。
实践中
从宏观层面来看,这很有道理。让我们来看看面向对象的 JavaScript 与纯函数式 JavaScript 有何不同。以下是一些函数式 JavaScript 代码:
let model = "Honda Civic";
let mileage = 50000;
function goVroom(typeOfCar){
console.log(`${model} goes vrooooom!!`})
};
function howOldIsMyCar(mileage){
console.log(`my car has ${mileage} miles.`)
};
function driveToSanDiego(mileage){
return mileage + 1000;
}
goVroom(model);
//=> Honda Civic goes vrooooom!!
howOldIsMyCar(mileage);
//=> my car has 50000 miles.
mileage = driveToSanDiego(mileage);
howOldIsMyCar(mileage);
//=> my car has 51000 miles.
这段代码可以运行,而且我们可以看出它与汽车的行为和属性相关。然而,这段代码在结构上没有任何关联。
如果我们用面向对象的方式编写之前的代码,它就能体现数据和行为方法之间的关系。这样的代码大概会是这样:
class Car {
constructor(model, mileage){
this.model = model;
this.mileage = mileage;
}
goVroom(model) {
console.log(`{this.model} goes vrooooom!!`);
}
howOldIsMyCar(mileage) {
console.log(`My car has ${mileage} miles.`);
}
driveToSanDiego(mileage){
this.mileage += 1000;
}
}
let jalopy = Car.new("astro", 150000);
jalopy
//=> Car {model: "astro", mileage:150000};
jalopy.goVroom()
//=> astro goes vrooooom!!
jalopy.howOldIsMyCar()
//=> My car has 150000 miles.
jalopy.driveToSanDiego()
jalopy
//=> Car {model: "astro", mileage:160000};
这里,Car 对象是一个类,或者说是 JavaScript 面向对象编程的基本结构。我们创建了这个类的一个实例,在本例中是 jalopy。它接受两个参数:model 和 mileage。我们定义的实例方法可以使用关键字this访问数据。this 指的是与该类关联的实例或特定对象。现在,我们的代码有了与特定数据实例关联的结构和方法。真棒!
结论:
面向对象编程是一种强大的代码组织方式,它允许相关数据的特定实例共享行为功能。我们已经讨论过,不仅在处理模型和后端时,而且在前端开发中,使用 JavaScript 提供的类对象构造函数,遵循这种编程实践都是非常有效的。