說到原型,肯定離不開對象,在JS中,我們創(chuàng)建的每一個函數(shù)都有一個prototype屬性,這個屬性是一個指針,指向一個對象,而這個對象的用途是包含可以由特定類型的所有實例共享的屬性和方法。
prototype
函數(shù)的 prototype 屬性指向了一個對象,這個對象正是調(diào)用該構(gòu)造函數(shù)而創(chuàng)建的實例的原型。
__proto__
這是每一個JavaScript對象(除了 null )都具有的一個屬性,叫__proto__,這個屬性會指向該對象的原型。
示例如下:
var obj = new Object()
console.log(obj.__proto__ === Object.prototype) // true
原型的原型
原型是一個對象,既然是對象,我們就可以用最原始的方式創(chuàng)建它,那就是:
var obj = new Object();
obj.name = 'Juff'
console.log(obj.name) // Juff
其實原型對象就是通過 Object 構(gòu)造函數(shù)生成的,實例的 __proto__ 指向構(gòu)造函數(shù)的 prototype
原型鏈
在 ECMAScript 中,每個由構(gòu)造器創(chuàng)建的對象擁有一個指向構(gòu)造器 prototype 屬性值的 隱式引用(implicit reference),這個引用稱之為 原型(prototype)。進(jìn)一步,每個原型可以擁有指向自己原型的 隱式引用(即該原型的原型),如此下去,這就是所謂的 原型鏈(prototype chain)
可以在瀏覽器控制臺下一直打印自己的原型,返回的都是一樣的。
原型鏈的定義是這樣的:

下面我們看一下實現(xiàn)原型鏈的一個例子:
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
}
function SubType() {
this.subproperty = false;
}
//繼承了SuperType
SubType.prototype = new SuperType();
SuperType.prototype.getSubValue = function () {
return this.subproperty;
};
var instance = new SubType();
console.log(instance.getSuperValue());
console.log(instance.getSubValue());
例子定義了兩個類型:SuperType和SubType,每個類型分別有一個屬性和一個方法。它們的主要區(qū)別是 SubType 繼承了 SuperType ,而繼承是通過創(chuàng)建 SuperType 的實例,并將該實例賦給SubType.prototype 實現(xiàn)的。實現(xiàn)的本質(zhì)是重寫原型對象,代之以一個新類型的實例。換句話說,原來存在于 SuperType 的實例中的所有屬性和方法,現(xiàn)在也存在于 SubType.prototype 中了。在確立了繼承關(guān)系之后,我們給 SubType.prototype 添加了一個方法,這樣就在繼承了 SuperType 的屬性和方法的基礎(chǔ)上又添加了一個新方法。
實際上,所有的引用類型默認(rèn)都繼承了Object,這個繼承也是通過原型鏈實現(xiàn)的。記住,所有函數(shù)的默認(rèn)原型都是Object的實例,因此默認(rèn)原型都會包含一個內(nèi)部指針,指向Object.peototype。