JavaScript到底是不是面向对象语言?
当然是。
为了讲清楚这个问题,我们需要先看一看「什么是面向对象编程」和「什么是面向对象语言」。
什么是面向对象编程?使用面向对象语言进行的编程就是面向对象编程。
什么是面向对象语言?在面向对象编程中使用的编程语言就是编程语言。
好吧,是不是感觉我说了两句废话,确实,编程语言可以自举,但是概念不可以。在讨论面向对象语言的时候,一般要界定这门语言的三个面向对象特征:封装、继承和多态。凡具有这三个特征,就是面向对象语言;不具有,就不是。
也有人讲过,面向对象特征有四个:封装、抽象、继承和多态,比一般的说法多了一个抽象。其实抽象不能算是面向对象的基本特征,因为在面向过程编程中,也有抽象;本质上编程就是抽象,就是将现实世界中一个或几个层面的东西剥离出来,用编程语言表达出来及进行交互控制。
进一步考察面向对象语言的三个基本特征,我们可以从语言的具体功能上重新阐述它们,这实际上还有助于我们记忆,否则,这三个特征名字你未必记得牢固。
先看封装。什么是封装功能?就是把属性、方法封装在一个类(class)中。你想一想,在你接触的编程语言中,C#、C++、Java 等,它们是不是允许我们这么干?
再看继承。什么继承功能?先定义(封装)了一个类 A,接着又定义了一个类 B,让 B 继承于 A,这样 A 的属性和方法(公开的)B 也有了(继承了)。
最后看一下多态。什么是多态?这是使用时的一个特征,与接口或虚类有关。先声明一个接口 I,然后让类 A 实现它,让类 B 也实现它。一个类型为 I 的变量,当它是类 A 的实例时,它具有类 A 的特性和行为特征,当它是类 B 的实例时,它又开始具有类 B 的特性和行为特征,这就是多态,仿佛有多个状态。
所以说,封装、继承和多态,这三个特征它们分别对应于语言中类的定义、类的继承和接口的定义和使用——这三个方面的能力,都有具体的功能含义。反观抽象,它明确对应于语言中的那个能力呢?没有,所以抽象并不能算是面向对象语言的一个基本特征。
最后,回头来看问题,JavaScript 是不是面向对象语言?那就看它具不具备三个面向对象的基本特征吧。
首先封装,JS 有 class,还有美元符号($)开头的私有属性,可以。然后是继承,ES6 有 extends,没问题。即使在 ES6 之前,也可以在一个对象上定义属性和方法,可以使用原型(prototype)实现对象之间的继承,对封装和继承的支持也没有问题。最后多态,也没有问题。虽然 JS 没有接口(它目前仅是保留了 interface 作为语言关键字),但是它的 Object 类型几乎是万能的,相当于是任何一个对象的接口,实现多态也完全不是问题。
使用 extends 关键字可以实现继承,使用原型也可以实现继承,它们只是实现方法不同,对应的面向对象的内在继承思想却是一致的。
最后,留给你两个思考题:
- Go 语言算是面向对象语言吗?
- 面向对象语言为什么会出现?