原型继承是面向对象编程中的一种代码重用形式。JavaScript是少数采用原型继承方式的主流面向对象语言之一,其他大部分面向对象语言都是经典继承。
在经典继承中,程序员编写一个类来定义一个对象,同一类别的多个对象可以从同一个类中实例化,因此您可以在一个地方编写描述程序中多个对象的代码。类别可以组织成层次结构,进一步提高代码的重用性。通用代码存储在较高层次的类别中,以便从低级别类别继承。这意味着一个对象与同一类别的其他对象以及其父类共享代码。
在原型继承中,对象直接从其他对象继承。所有关于类的业务都消失了。如果要创建一个对象,只需要编写一个对象即可。但是代码重用仍然是有价值的,因此允许将对象链接在层次结构中。在JavaScript中,每个对象都有一个指向创建它的对象的秘密链接,形成一个链。当请求一个对象没有的属性时,会向上沿着链询问其父对象...直到找到该属性或者到达根对象为止。
JavaScript中的每个函数(它们本身也是对象)实际上都有一个名为“prototype”的成员,该成员负责在请求一个对象的值时提供值。拥有这个成员可以使构造函数机制(通过该机制使用函数构造对象)工作。向函数对象的原型添加属性将使其对于构造出的对象和继承自它的所有对象都可用。
优点
为什么原型继承是一种有利的代码重用形式可能没有硬性规定。代码重用本身就是有利的,而原型继承是一个明智的选择。你可能会认为原型继承是一种相当简单的代码重用模型,代码可以通过直接方式大量重用。但传统语言当然也能够做到这一点。
附注:@Andrew Hedges 指出,实际上有许多基于原型的编程语言。(参见链接)这些语言的存在值得注意,但也值得注意的是,它们中没有一种是流行的。NewtonScript 似乎曾经有一些影响力,但随着平台的消失而消亡。还可以通过扩展一些现代语言的方式,添加原型功能。
一种基于原型的语言不区分类和对象:它只有对象。一个基于原型的语言具有原型对象的概念,这是一个用作模板的对象,从中获取新对象的初始属性。任何对象都可以在创建时或运行时指定自己的属性。此外,任何对象都可以关联为另一个对象的原型,使得第二个对象共享第一个对象的属性。
基于原型(Prototype-based)的编程是一种面向对象编程风格,其中没有类,而是通过克隆充当原型的现有对象来实现行为复用(或在基于类的语言中实现继承)。
不需要声明一个类结构,你可以创建相同类型的对象,并且随时使用对象的原型来添加到它们的定义中。这比通常的做法更加灵活。
如果您仅在运行时使用对象而不是在编译时使用类来构建新对象,则可以扩展对象而无需了解任何详细信息。当然,这取决于使用方式,很快可能会变成一个劣势。我在此不对语言做任何假设,因此适用于其他不太动态的语言,而不仅仅是javascript。
myobject.prototype=unkownobject;
myobject.newproperty=1;
JavaScript的原型继承具有内存保护的优势。在像Java这样的语言中,对象会生成它们自己的超类实例变量和方法的副本,而在JS中,“super”对象为每个从它继承的“sub”对象提供访问其变量和方法的途径,而无需重新创建它们。