定義
在 JS 裏 prototype
是一個被稱作對象的原型屬性,這個屬性任然是一個對象,它可以作爲所有新副本的基引用 (base reference) 。我們可以給這個原型對象添加屬性,這些屬性成爲了由它實例化出來的所有對象的公有屬性。
我們可以對比其他強類型語言如 Java 中類定義的非靜態屬性和函數(public),是屬於所有該類的所有對象,也就像這裏的 base reference。所以在 Java 中描述靜態成員與非靜態成員時有:
靜態成員整個類中只有一份,而非靜態的成員每個對象都有一份
例子
// classA 的構造器
function classA(numberA) {
this.numberA = numberA;
}
classA.staticVal = "static value";
// 一個 classA 的實例
var objRefA = new classA(2);
// 給 classA 的原型對象添加一些屬性
classA.prototype.getNumberA = function() {
return this.numberA;
};
classA.prototype.typeName = "type name is classA";
console.log( objRefA.getNumberA() ); // 2
console.log( objRefA.typeName ); // type name is classA
console.log( objRefA.staticVal ); // undefined
console.log( objRefA.constructor.staticVal ); // static value
比較有趣的是弱語言沒有強語言那麼嚴謹,但是他非常靈活。這裏的對象在實例化之後通過原型對象 prototype 給他增添了一個 getNumberA 的函數和一個 typeName 的屬性。同樣對象是無法直接訪問到 classA 的成員的,但是我們可以通過 constructor 屬性作爲我們訪問 classA 中的成員的一座橋樑。
思考:前面有提到 Java 中對象可以直接訪問類中的 public 的成員,private 的成員無法直接訪問。那麼我們弱語言中可以實現這種 private 的成員呢?
通過 prototype 繼承
說到繼承,還是先聊一聊強類型語言 Java 中的實現,在 Java 中子類中使用 extends 關鍵字即可實現。子類中可以訪問基類對子類開放的成員 ( public
、protected
)
// 基類
function baseClass() {
this.key = "base";
}
// 子類
function classB (name) {
this.name = name;
}
// 通過將基類的對象賦值給子類的原型對象,使得子類擁有基類的全部可見成員
classB.prototype = new baseClass();
var objRefB = new classB("b");
console.log(objRefB.key); // base