Javascript是基于原型的语言,这意味着什么?


Answers:


291

原型继承是一种面向对象的代码重用形式。Javascript是使用原型继承的仅有的[主流]面向对象语言之一。几乎所有其他面向对象的语言都是经典的。

经典继承中,程序员编写一个类,该类定义一个对象。可以从同一类中实例化多个对象,因此您将代码放在一个位置,该代码描述了程序中的多个对象。然后可以将类组织成一个层次结构,以促进代码重用。更通用的代码存储在较高级别的类中,较低级别的类从中继承。这意味着一个对象正在与同一类的其他对象及其父类共享代码。

原型继承形式中,对象直接从其他对象继承。关于类的所有事务都消失了。如果需要对象,则只需编写一个对象。但是代码重用仍然是很有价值的事情,因此允许将对象按层次结构链接在一起。在javascript中,每个对象都有一个秘密链接到创建它的对象,形成一个链。当要求对象提供其不具有的属性时,将询问其父对象...一直沿链向上,直到找到该属性或到达根对象为止。

JavaScript中的每个函数(本身就是对象)实际上都有一个称为“原型”的成员,该成员负责在请求对象时提供值。具有此成员可以使构造函数机制(通过该机制从函数构造对象)起作用。向功能对象的原型添加属性将使其对构造的对象以及从其继承的所有对象可用。

优点

关于原型继承为何是代码重用的一种有利形式,可能并没有一个严格的规则。代码重用本身是有利的,而原型继承是实现它的明智方式。您可能会争辩说,原型继承是代码重用的相当简单的模型,并且代码可以直接方式大量重用。但是古典语言当然也能够做到这一点。

旁注: @Andrew Hedges提出了一个很好的观点,即实际上有许多原型语言。值得一提的是,还有其他人存在,但也没有一个人比主流更重要。NewtonScript似乎有一段时间受到关注,但由于其平台而死。也可以通过添加原型功能来扩展某些现代语言。


9
凯利 尽管JavaScript是迄今为止最受欢迎的原型语言,但还有许多其他语言:en.wikipedia.org/wiki/Prototype-based_programming#Languages
Andrew Hedges

2
嘿,安德鲁。好点子。我应该更清楚了。我会记录下来。
keparo


1
+1是个不错的答案。一个小评论:在我看来,古典继承似乎比原型更为“直接”。实际上,我确实将原型对象看作仅仅是(与其他对象的)链接,而在编译的OOP中,我认为基类是“直接继承的”。因此,原型对象是链接在一起的,而不是继承的(继承是伪造的)。有什么想法吗?
囚犯零

3
@PrisonerZERO:我认为原型继承比经典继承更直接。它没有直接指向对象A指向的类,而是直接指向对象A并说“我就像那个对象,除了...”,而不是对象B指向从对象A所指向的类继承的类。关于原型继承的最大问题,对于大多数人而言,似乎很难被内部化的事情是,它不能将实例与类型区分开。每个对象都是类型和实例。两者之间的区分是人为和故意的,通常是卡在面向类的思维模式中的征兆。
cHao 2014年

54

基于原型的语言不会区分类与对象:它只是具有对象。基于原型的语言具有原型对象的概念,该对象用作模板,从模板获取新对象的初始属性。任何对象都可以在创建对象时或在运行时指定其自己的属性。此外,任何对象都可以关联为另一个对象的原型,从而允许第二个对象共享第一个对象的属性。


6
一个很好的解释,但对“初始属性模板”的评论有点误导。如果在实例化对象后更改原型,该对象仍将接收那些功能。
尼克

32

基于原型的编程是一种不存在类的面向对象编程,并且通过克隆用作原型的现有对象来执行行为重用(或基于类的语言的继承)。


你还是这样吗?因为如果是这样,那么这是我真正坚决地“单击”我的第一个解释。
Chazt3n

11

优点/缺点是,我们可以在运行时创建新型对象,而无需定义类(静态代码)。像大多数功能一样,由开发人员决定将其变成优点/缺点。

上面的可能是因为对象本质上是Java脚本中的函数(也有闭包)。


动态对象是javascript的一项优势,但它们与javascript作为原型或功能语言并没有真正的关系。在许多经典语言中,您可以在运行时创建动态对象。关闭也有些无关。
keparo

2
类不一定是静态代码-请看一下Python,其中类本身是对象,并由同样是对象的元类构造而成。
TomaszZieliński,2010年

6

您可以创建相同类型的对象,而不用声明类结构,并在需要时使用对象的原型将其添加到它们的定义中。它比常规的处理方式更灵活。


6

如果仅在运行时使用对象,而不是在编译时使用类来构建新对象,则可以在不了解对象详细信息的情况下扩展对象。当然,根据使用情况,它可能很快成为缺点。我在这里不对语言进行任何假设,因此它适用于非javascript而不是动态语言。

myobject.prototype=unkownobject;
myobject.newproperty=1;

您可以从几乎任何地方获得对象。您自己的代码,来自网络,来自数据库,来自外部链接等。

请注意,一种语言不必像javascript一样实现原型继承。在javascript中,原型对象仅在继承者之间共享,其属性也共享。替代方法是将原型的所有属性复制到新对象。每种方法在不同情况下都有其优势。我喜欢第二个,但这不是javascript的功能。


6

阅读所有答案后,得出结论

1)继承,对象直接从其他对象继承

2)不使用类

3)也称为基于实例的编程或面向无类原型的编程

4)通过克隆用作原型的现有对象来执行行为重用

5)从新对象中用作模板的对象获得初始属性

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.