发布于 2026-01-06 1 阅读
0

为什么 JavaScript 是一种面向对象编程语言(即使它没有类)

为什么 JavaScript 是一种面向对象编程语言(即使它没有类)

你可能了解面向对象编程(OOP)的工作原理。类Dog继承自类Animal,这意味着如果你有一个类,Dog你可以访问类的方法Animal。这实际上只是面向对象编程的一个子集。你可以不用类来实现面向对象,而 JavaScript 正是这样做的。

类就像一张蓝图,它包含了该类每个实例所拥有的信息。它告诉你该类有哪些方法和属性,以及如何使用它。

类本身并不包含任何数据。那是对象的职责。类就像房子的蓝图,而对象才是真正的房子,它包含木材、瓦片、砖块以及房子应有的所有重量。实例则包含仅属于该实例的实际数据。你可能和邻居使用了相同的房屋蓝图,但这并不意味着你可以睡在他们的床上。

实例和类的区别是大多数人理解面向对象编程(OOP)的根本所在。但对于OOP来说,这并非必要条件。完全可以不用类来实现OOP。毕竟,面向对象编程的核心在于对象,而非类。

面向对象编程中类和对象之间没有区别的风格称为基于原型的编程(为了方便起见,我们称之为 PBP)。

在PBP中,每个对象都是独立的个体。它同时包含方法数据。通常,您可以随时向对象添加新的属性和方法,即使程序正在运行时也可以。

如果你觉得这像是只有少数程序员才会用来处理特殊情况的工具,那就大错特错了。世界上最流行的编程语言之一就是一种基于过程的编程语言:JavaScript。

在 JavaScript 中,没有传统意义上基于类的面向对象编程(OOP)中的类。JavaScript 使用对象。如果你想将一些函数和属性封装在一起,你应该创建一个包含这些函数和属性的对象,而不是一个类。

const animal = {
    numberOfLegs: 4,
    sleep: () => print("Zzz")
}

这是一个包含属性和执行特定操作的函数的对象。它与类不同,因为函数本身也是对象拥有的一段数据。它与属性的状态一样可变。

animal.sleep = null

现在,突然之间,动物就没有功能了。JavaScript 没有蓝图,只有房子。

那么继承权呢?

类的一个基本属性是它可以从其他类继承方法和属性。AHouse和 B都Apartment可以继承自同一个Residence类,以确保我们不必在两个类中重复编写相同的代码。

但是,类并非继承的必要条件。在PBP中,继承完全是通过对象来实现的。

我之前提到过,在原型驱动编程(PBP)中,一个对象包含它的所有方法、属性以及它们的实际状态。因此,继承所有这些方法和属性的唯一方法是复制(或引用)它们。这正是原型驱动编程语言的工作原理,它被称为原型继承

如果我们想要创建一个dog可以访问与 相同方法的对象animal,我们可以简单地让dog 包含 animal,因为这些方法在 内部animal

const dog = {
    prototype: animal,
    bark: () => print("Woof!")
}

如果我们想让dog食物被吃掉,我们可以这样做:

dog.prototype.eatFood(10)

幸运的是,JavaScript 会自动调用原型上的函数。如果某个函数不存在于该对象上,它会在原型中查找该函数。原型本身可以包含另一个原型,因此 JavaScript 会一直向上查找,直到找到它需要的函数为止。

之所以称之为基于原型的语言,是因为原型(而非类)是具体的。原型是实际运行的东西,而不是蓝图。你可能不会把原型卖给数百万客户,但它是真实存在的,可以正常运行。然后,你可以使用这个原型来构建大量实际使用的副本,就像在工厂里一样。

这个animal物体是某种动物的原型。它和其他物体一样,但它将被用来创造新的、具体的动物,比如dog……

这比上课好吗?

PBP(基于模型的编程)比基于类的面向对象编程更直接。它的组件更少,而且完全透明,你可以清楚地看到它的工作原理。基于类的面向对象编程则是在其之上增加了一层抽象。这意味着PBP有很多优点,但也存在一些缺点。

PBP(基于项目的编程)的主要优势在于其灵活性。蓝图必须预先绘制,而且必须准确无误。如果你正在建造房屋,却在建造屋顶的过程中才发现忘记在蓝图中添加窗户,那将会非常麻烦。类也是如此:你必须创建类,然后才能创建和使用对象。在使用类之前,你必须知道需要哪些方法和属性。无论你的编程水平多么高超,你都无法预测所有情况。

如果无需预先创建类,您就可以立即开始创建对象。您可以在使用过程中随时调整它们,而无需付出高昂的代价。这在编程中非常有利,因为需求总是不断变化。您需要能够快速轻松地进行更改。

但快速便捷的修改也伴随着巨大的风险:正确性。蓝图的作用是在建造房屋之前进行规划,以便及早发现错误,避免工人在施工过程中迷失方向。如果你只是随心所欲地建造房屋,最终很可能是房子坍塌砸在你身上。编程也是如此:你需要确保代码库的健全性和正确性。如果任何人都可以随意修改代码,它很快就会崩溃瓦解。

就像编程中的其他所有方面一样,基于过程的编程(PBP)和基于类的面向对象编程(OOP)之间存在着权衡取舍。一方面,PBP 灵活易用,可以加快开发速度。另一方面,基于类的 OOP 更加严谨可靠,可以减少 bug 的出现。不同的问题需要不同的工具,而掌握了 PBP 的知识后,你就能更好地解决需要用到它的问题。祝你编程愉快!

注:本文转载自programmingwords.com。这是一个每月介绍两个计算机科学新术语的博客。如果您对计算机科学、编译器或编程语言感兴趣,不妨去看看!:)

参考:

基于原型的编程

https://en.wikipedia.org/wiki/Prototype-based_programming

继承和原型链 - JavaScript

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

文章来源:https://dev.to/marinbenc/why-javascript-is-an-oop-language-even-though-it-doesnt-have-classes-39m2