傳統的OO語言有類的概念,但js(ES5)倒是基於原型實現的面向對象。babel
原型是?
咱們建立的每個函數都會有一個原型(prototype)屬性,這個屬性是一個指針,指向函數的原型(prototype)對象。使用原型對象可讓構造函數的實例對象共享原型對象包含的屬性和方法,而不會像工廠模式或者構造函數模式那樣,方法本應該是能夠是通用的,但是每個建立的對象實例都要各自複製一份。函數
function People(name){ this.name=name; this.sayName=function(){ console.log("Hi! my name is "+this.name); }; }
var Jerel=new People("Jerel"); var AsenZ=new People("AsenZ"); console.log(Jerel.sayName==AsenZ.sayName); //false
但使用原型模式的話,同一個方法是被不一樣對象實例所引用的,上面的結果會返回ture。this
function People(name){ this.name=name; } People.prototype.sayName=function(){ console.log("Hi! my name is "+this.name); }; var Jerel=new People("Jerel"); var AsenZ=new People("AsenZ"); console.log(Jerel.sayName==AsenZ.sayName); //true
構造函數實例化的過程當中發生了什麼spa
構造函數經過new操做符實例化的每個對象,都會生成一個指向構造函數原型對象的指針,不過在這裏不是prototype(構造函數經過prototype指針指向原型對象),而是[[prototype]](或者叫—proto—),同時構造函數內部的this指針會綁定到該對象實例上。prototype
構造函數內部綁定在this指針下的全部屬性或者方法會被複制下來,做爲實例對象的一部分,可是呢原型中定義的屬性和方法還是屬於原型自身的,不歸對象實例全部。對象只是引用。對象在調用一個屬性或者方法時,若是在構造函數內部沒有相應的定義,則會經過[[prototype]]指針去原型對象中尋找。指針
繼承code
——借用構造函數對象
若是須要繼承構造函數內部this指針所綁定的全部屬性和方法的話,能夠在子構造函數中使用call方法,call方法的第一個參數會傳入一個對象,這個對象會用來替換調用call方法的方法中的this,因此咱們call方法的第一個參數能夠傳入子構造函數內部的this指針。blog
可是這種方法卻繼承不了原型內部的屬性和方法。繼承
function People(name){ this.name=name; } People.prototype.sayName=function(){ console.log("Hi! my name is "+this.name); }; function Boy(name){ People.call(this,name); } var Jerel=new Boy("Jerel"); console.log(Jerel.name); //Jerel console.log(Jerel.sayName); //undefined
若是須要繼承原型對象的內部屬性和方法的話呢?
——組合繼承(借用構造函數+原型鏈)
function People(name){ this.name=name; } People.prototype.sayName=function(){ console.log("Hi! my name is "+this.name); }; function Boy(name){ People.call(this,name); } Boy.prototype=new People(); Boy.prototype.constructor=Boy; var Jerel=new Boy("Jerel"); console.log(Jerel.name); //Jerel Jerel.sayName(); //Hi! my name is Jerel
還有很多其餘的實現繼承的方法,不過感受思路差不了多少的,這一篇總結主要是爲了加深一下本身對原型的理解。
雖說有了babel,如今ES6已經能夠放開的使用了!class定義類,extends實現繼承不能再爽,可是這些新特性也不過是語法糖,底層的原理仍是離不開最基本的原型。