原型程式設計

原型程式設計（英語：prototype-based programming）或稱為基於原型的編程、原型編程，是物件導向程式設計的子系統和一種方式。在原型編程中，類不是實時的，而且行為重用（通常認為繼承自類別基礎的語言）是通過複製已經存在的原型物件的過程實現的。這個模型一般被認為是 classless、面向原型、或者是基於實體的編程。
原型編程最初的（也是最經典的）例子是程式語言 Self，它是由 David Ungar 和 Randall Smith 開發的。但是 classless 編程方式最近變得越來越受歡迎，並且被 JavaScript、Squeak (當使用觀察者框架操作 Morphic 元件時)、Cecil、NewtonScript、Io、MOO、REBOL 還有一些其他的程式語言所採納。

與類別基礎編程的比較

在類別基礎編程當中，物件總共有兩種類型。類別定義了物件的基本布局和函式特性，而介面是「可以使用的」物件，它基於特定類的樣式。在此模型中，類表現為行為和結構的集合，就介面持有物件的資料而言，對所有介面來說是相同的。區分規則因而首先是基於結構和行為，而後是狀態。
原型編程的主張者經常爭論說類別基礎的語言提倡使用一個關注分類和類之間關係開發模型。與此相對，原型編程看起來提倡程式設計師關注一系列物件實體的行為，而之後才關心如何將這些物件劃分到最近的使用方式相似的原型物件，而不是分成類。因為如此，很多基於原型的系統提倡執行時原型的修改，而只有極少數類別基礎的物件導向系統（比如第一個動態物件導向的系統 Smalltalk）允許類在程式執行時被修改。
原型編程常與認知心理學的特定思想流派有關，同樣強調prototypes 和 exemplars 作為學習過程中的關鍵詞。
考慮到絕大多數基於原型的系統是基於解釋性的和動態型別程式語言，這裡要重點指出的是靜態型別語言實現基於原型從技術上是可行的。用基於原型編程描述的 Omega 語言就是這樣系統的一個例子。儘管根據 Omega 網站所述，Omega 也不是完全的靜態，但是可能的時候，它的編譯器有時會使用靜態繫結來改行程序的效率。

物件構造

在類別基礎的語言中，一個新的實體通過類構造器和構造器可選的參數來構造，結果實體由類選定的行為和布局建立模型。在基於原型的系統中構造物件有兩種方法，通過複製已有的物件 或者通過擴充 nihilo（空的）物件建立，因為大多數系統提供了不同的複製方法，擴充 nihilo 物件的方式鮮為人知。
提供擴充 nihilo 物件建立的系統允許物件從空白中建立而無需從已有的原型中複製。這樣的系統提供特殊的文法用以指定新物件的行為和屬性，無須參考已存在的物件。在很多原型語言中，通常有一個 Object 原型，其中有普遍需要的方法。它被用作所有其它物件的最終原型。擴充 nihilo 物件建立可以保證新物件不會被頂級物件的命名空間污染。(在JavaScript中，可以利用null原型來做到, i.e. Object.create(null))。
Cloning 指一個新物件通過複製一個已經存在的物件（就是他的原型）來構造自己的過程。於是新的物件擁有原來物件的所有屬性，從這一點出發新物件的屬性可以被修改。在某些系統中，子物件持有一個到它原型的直接連結（經由授權或類似方式）。並且原型的改變同樣會導致它的副本的變化。其他系統中，如類 Forth 的程式語言，Kevo 在此情況下不傳播原型的改變，而遵循一個更加連續的模型，其中被複製的物件改變不會通過他的副本傳播。
// Example of true prototypal inheritance style // in JavaScript.// "ex nihilo" object creation using the literal // object notation {}.var foo = {name: "foo", one: 1, two: 2};// Another "ex nihilo" object.var bar = {three: 3};// Gecko and Webkit JavaScript engines can directly // manipulate the internal prototype link.// For the sake of simplicity, let us pretend // that the following line works regardless of the // engine used:bar.__proto__ = foo; // foo is now the prototype of bar.// If we try to access foo's properties from bar // from now on, we'll succeed. bar.one // Resolves to 1.// The child object's properties are also accessible.bar.three // Resolves to 3.// Own properties shadow prototype propertiesbar.name = "bar";foo.name; // unaffected, resolves to "foo"bar.name; // Resolves to "bar"
下面是個在 JavaScript 1.8.5 以上版本的例子（參見 http://kangax.github.com/es5-compat-table/ ）
var foo = {one: 1, two: 2};// bar.[[ prototype ]] = foovar bar = Object.create( foo );bar.three = 3;bar.one; // 1bar.two; // 2bar.three; // 3

委託

在使用委託的基於原型的語言中，執行時語言可以僅僅通過循著一個序列的指標直到找到符合這樣的方式來定位屬性或者尋找尋找正確的資料。所有這些建立行為共用的行為 需要的是委託指標。不像是類別基礎的物件導向語言中類和介面的關係，原型和他的分支之間的關係並不要求子物件有相似的記憶體結構，因為如此，子物件可以繼續修改和...而無須像類別基礎的系統那樣整理結構。還有一個要提到的地方是，不僅僅是資料，方法也能被修改。因為這個原因，大多數基於類型的語言把資料和方法提作「slots」。

關聯

在純粹的原型，又被稱作 concatenative 原型（以 Kevo 語言為例）中沒有到被複製的原型物件的指標或連結。原型物件以重新給定名字（或參照）的方式被確實的複製了。這個過程類似於生物學上的分裂，屬性和方法被原樣複製。
這樣做的好處包括物件的作者可以修改這份副本而無須擔心對此父類別的其他子類別產生副作用。進一步的優點是尋找屬性運算的消耗同授權相比大大降低了，授權尋找必須遍歷整個委託鏈才能判定不存在。
Concatenative 的壞處包括傳播變化到整個系統的難度；如果一個變化作用到某個原型，它不會立即或者自動的對它的所有副本生效。然而Kevo提供了額外的在物件系統中傳播變化的方式。這種方式是基於他們的相似性（所謂的 family 相似）而非像委託模型具有代表性的那樣源自分類學。
另外一個壞處是在這個模型的大多數自然的實現下，每一個副本上都有額外的記憶體被浪費掉了（相對委託模型而言），因為副本和原型之間有相同的部分存在。然而，在共用的實現和後台資料中提供 concatenative 行為的編程編程是可行的。這種做法為 Kevo 所遵從。

批評

那些經常批評基於原型系統而支援類別基礎的物件模型的人通常有類似靜態型別系統相對於動態型別系統的擔心。通常這些擔心是：正確性、安全性、可預測性以及效率。
在前三點上，類可以看作和類型等效（多數靜態語言遵守此規則）而且提供保證他們實體的契約，而對這些實體的使用者保證特定場景中的行為。
在最後一點上，效率，類的聲明簡化了編譯器的組織，允許開發高效的方法以及實體變數尋找。對Self語言來說，大多開發時間都消耗在開發、編譯以及解釋技術用以改進基於原型的系統相對於類別基礎的系統。舉例來說 Lisaac 產生的程式碼速度幾乎跟C一樣快。測試是由 MPEG-2 編碼器的 Lisaac 版本得出的，它由一個C語言版本複製而來。測試顯示，Lisaac 版本比 C 版本慢1.9%，但程式碼行數少了37%。然而C語言並非物件導向語言，而是一個程序式語言。Lisaac 跟 C++ 版本相比可能更說明問題。
最普遍的對基於原型的語言的批評來自不喜歡它的軟體開發者社群，僅管有 JavaScript 的人氣和市場。對基於原型系統的了解程度似乎因為JavaScript 框架的廣泛應用以及 JavaScript 針對 Web 2.0的複雜應用而改變。很可能由於這些原因，在 ECMAScript 標準的第四版開始尋求使 JavaScript 提供類別基礎的構造，且ECMAScript 第六版有提供"class"(類)作為原有的原型架構之上的語法糖，提供建構物件與處理繼承時的另一種語法。