原型
在javascript中,原型分有兩種:顯示原型(prototype)和隱式原型(__proto__)。
__proto__(隱式原型)
JavaScript中任意對象都有一個內置屬性`prototype`,在ES5之前沒有標準的方法訪問這個內置屬性,但是大多數瀏覽器都支持通過__proto__來訪問。ES5中有了對於這個內置屬性標準的Get方法Object.getPrototypeOf().
prototype(顯式原型)
這是函數對象特有的屬性。這個屬性是一個指針,指向一個對象,這個對象的用途就是包含所有實例共享的屬性和方法(我們把這個對象叫做原型對象)。原型對象也有一個屬性,叫做constructor,這個屬性包含了一個指針,指回原構造函數。
例如:
var a = {}; console.log(a.__proto__); // => Object {…} console.log(a.prototype); // => undefined function b(){} console.log(b.__proto__) // => function () { [native code] } console.log(b.prototype) // => Object {…}
注:Object.prototype的__proto__值爲null。
區分__proto__與prototype
定義
這兩個名次的概念在上文中已經做了解釋,不贅述。
作用
prototype:用來實現基於原型的繼承與屬性的共享。
__proto__:構成原型鏈,同樣用於實現基於原型的繼承。
二者的關係
__proto__在es5裏指向構造函數的prototype,在es6裏指向該構造函數。
小結
1.任意對象(在javascript中,所有東西都是對象)都有屬性__proto__,指向該對象的構造函數的原型對象(prototype)。
2. 函數對象除了有屬性__proto__,還有屬性prototype,prototype指向該方法的原型對象(prototype)。
原型鏈
在javascript中,每個對象和原型對象(prototype)都有一個原型(__proto__),對象的原型指向構造函數(父)的原型對象(prototype),而原型對象(prototype)的原型(__proto__)指向父的父的原型對象(prototype),這樣便形成了通過原型層層連接起來的關係,我們把它稱爲原型鏈。聽起來很拗口,我簡單畫了個圖希望能幫助你理解:
由上圖可見,__proto__是實現原型鏈的關鍵,而prototype則是原型鏈的組成。另外,所有構造器/函數的__proto__都指向Function.prototype,它是一個空函數(Empty function)。
原型鏈繼承
在訪問一個對象的某個屬性時,首先在該對象的內部查找,若有則返回給屬性值,若沒找到,則從該對象的原型(__proto__)所指向的原型對象(構造器的prototype)中查找,若還是找不到,則繼續從該原型對象(prototype)的原型(__proto__)所指向的原型對象中查找,以此類推,知道找到爲止,若找不到則返回undefined。
利用這一思想,我們直接將子類的原型對象指向父類的某個實例,則子類創建的所有實例都會繼承了父類的所有屬性,這就是原型鏈繼承。如:
function Parant (name, age) { this.name = name; this.age = age; } Parant.prototype.say = function(){ console.log('hello, my name is ' + this.name); }; function Child() { } Child.prototype = new Parant('pursue'); var man1 = new Child(); man1.say(); //hello, my name is pursue var man2 = new Child(); console.log(man1.say === man2.say);//true console.log(man1.name === man2.name);//true