JS 为什么要用prototype来实现面向对象?

当初这门语言的设计者到底是如何想的,它的实现看上去与其他语言如此不同。是为了要解决什么特殊目的,或者有什么特殊需求吗?

阅读 10.9k
7 个回答

Brendan Eich 不止一次地在公开场合(比如会议演讲或个人博客上)回顾了 Javascript 的诞生和成长历程,当然也包括了很多关于原型继承的内容,当初的历史远不是现在口口相传的“奇闻异事”那么简单。

我觉得在草率写下答案之前还是去仔细的回顾下这段历史吧,最起码把 Youtube 上 Brendan Eich 的演讲和访谈都看过一遍再来评价他当初的设计选择。

如果我们单纯的认为 Javascript 是一个“只花了十天”的“应付差事”的语言,又怎么解释 Javascript 今天的“江湖地位”?不要说在浏览器上没有竞争者,许多企业都曾尝试过。

只说原型继承,不管读到这里的诸位之前对原型继承有无偏见,建议你先精读这篇文章:Why Prototypal Inheritance Matters,然后再看看作者在 SO 上如何回答同样的问题

此后若还是有偏见,那我只能说 OO 的真谛并不在乎于语言用什么样的模式去实现它。每一个人偏好哪种真是仁者见仁智者见智了,一定要分出个高下,辨出谁好谁孬简直是庸人自扰。

另外直接回答题主的问题:Javascript 在设计最初选择了原型式面向对象的最直接原因就是“简单”。遗憾地是在很长一段时间里,原型的简单被滥用构造器模式的风潮所遮掩。这种滥用可能会有很多原因,普遍认可的原因是 Javascript 诞生和发展的早期尚没有一门原型式面向对象语言在应用领域被广泛认知,而那时恰好前端也不成气候,整个 web 开发界没有正确的认识到该如何理解和使用原型式面向对象语言。同时 Javascript 的缔造者们在宣传和推广 Javascript 上也受到了诸多限制与影响,从而导致最早一批使用 Javascript 的开发者们“自然而然”的去寻求与 Java 等语言更接近的 OO 实现。

在此后的“拨乱反正”是相当艰难的,因为气候已成,成见已生,再加上那一段“标准不能标准”的黑暗时代的负面影响,导致 Javascript 一直以来都不能以本来面目示人。ECMAScript 做过多次尝试,比如说 5 的时候扩充了许多 API 去减弱构造器模式的“统治性地位”并给那些探索原型式继承的开发者们提供更多“武器”。到了 6 则干脆加上了 Class 这个语法糖——但令人痛心的是:时至今日还有人认为新的 Class 语法是在丢弃原型式 OO 而转投类型式 OO 的阵营!不是这样的啊! Class 只是语法糖而已,底层对于 OO 的实现完全还是经典的原型式 OO,加这么个语法糖纯粹就是为了简化语法另外让初学者更容易上手和接受罢了。

有时候我也在想加 Class 对 Javascript 到底是好事还是坏事?也许对于语言来说是好事,但是对于原型式 OO 来说就真的祸福难料了。当新人上手就写惯了 Class,他们还有多少人会对原型式 OO 有兴趣?我个人认为如果只钻研过一种 OO 的实现模式真的很难理解 OO 的真谛,至少也要花费很多的时间才能体会。但若是能两相比较的话就会好得多……这是题外话,打住不谈。

这得从js设计者Brendan Eich发明js开始说起了,在那个上网速度比蜗牛还慢的时代,网景公司(Netscape)急需一种脚本语言,使得浏览器和网页进行交互,从而提升用户的体验。当时Brendan Eich想设计一门用于网页交互的语言,然后参考了java(他仅用十天便发明了js),但是他又不想像java那样用class来实现继承,最后就搞出了个prototype,利用prototype的原型链来实现继承。

总的来说啊,Brendan Eich设计思路是这样的:

  1.借鉴C语言的基本语法;
  2.借鉴Java语言的数据类型和内存管理;
  3.借鉴Scheme语言,将函数提升到"第一等公民"(first class)的地位;
  4.借鉴Self语言,使用基于原型(prototype)的继承机制。
所以,Javascript语言实际上是两种语言风格的混合产物(简化的)函数式编程+(简化的)面向对象编程。这是由Brendan Eich(函数式编程)与网景公司(面向对象编程)共同决定的。

虽然已经有采纳答案,还是想要回答,因为对路。

有一门OO语言基础的人,学习js是有不少难度的。

因为他们总是会问

1. 我在x语言中的封装,js如何做?
2. 我在x语言中的继承,多态,js如何做?
...

从认知论角度看:以类比的方法,用熟悉的事物去套新事物,是人类的常见的学习套路,有助于减轻焦虑,尽量不离开舒适区,但是仅仅适合差别比较小的一堆实体,比如c#和java。

可问题在于,js不是OO语言,js也不曾想要用prototype实现oo(是oo的人希望js实现oo,而方法就是prototype)。js的prototype就是prototype!

正如oo有一堆语言一样,prototype也是,比如self,io。他们各有自己的方法论,各不相同,但是都可以解决现实问题。

这里提到的他们,其实就是我。

有一天,我终于认识到,我应该理解和学习js本身,而不是类比和套用。于是,后面就是坦途了。

这就是我为此写的一篇blog

应该说是原型,js不是OO,只是人们习惯OO后 有OO的写法而已

新手上路,请多包涵

记得刚开始学js的时候,因为它的面向对象和其它不一样,很是抵触。
后来比较系统的学习后,才知道这种模式挺精妙的!

Javascipt: The Good Parts

当Java Applet陨落的时候,Javascript成为了web编程的缺省语言,但它的流行程度跟它作为一个编程语言的质量完全没有关系。(When Java applets failed, Javascript became the language of the Web by default; its popular is almost completely independent of its qualities as a programming language.)

javascript从语言的设计到标准的定稿只花了最多不过2年时间(C语言从设计到定稿花了接近20年),据说设计这门语言只花了差不多半个月。所以它作为一门面向对象的语言,它的面向对象采用的是最简单快速的prototype来实现,没有别的语言那么严谨。当初设计js的目的就只是用它来在浏览器端能做一些简单的验证表单的功能(不用每次提交到服务器进行验证),减轻服务器的压力和带宽的压力。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏