剛開始接觸對象原型時大腦就開始起義了,腦子就轉不靈清了。就感覺怎么着這個概念就是灌輸不進去,俗稱斷路。后面找了很多資料,最主要的還是要借助於《JavaScript語言精髓》這本書,讓我對這此豁然開朗,希望說的不對的地方請給予指正,謝謝。
一、什么是原型?
原型包含一個對象("prototype"對象),是構造函數特有的屬性。將所有實例對象共享的屬性和方法放在里面,不需要共享的屬性和方法則放在構造函數里面。它能繼承私有和共享屬性和方法。
二、prototype實例
首先創建一個構造函數,具有name屬性。
function Person(name){ this.name = name; }
構造函數創建好之后,我想創建兩個實例,並且輸出他們的name值。
var p1 = new Person("張三"); var p2 = new Person("李四"); console.log(p1.name+","+p2.name); /* 輸出張三,李四*/
那現在我想給p1張三在添加一個eat屬性,我要他可以吃飯(food),那既然你張三都可以吃飯,那我李四要要吃飯,那我也輸出p2.eat,但是結果是undefined……如下所示。
p1.eat = "food"; console.log(p1.eat); /* 輸出food */ console.log(p2.eat); /* 輸出undefined */
原來是張三自己偷偷摸摸的去吃飯,沒讓李四知道,哎╮(╯▽╰)╭。那既然這樣,Person就不得不添加一個共用屬性eat了,得讓大家一起吃飯呀。
Person.prototype.eat = "food"; console.log(p1.eat); /* 輸出food */ console.log(p2.eat); /* 輸出food,我也可以吃飯了…… */
添加Person.prototype.eat = "food"這個以后,eat屬性就被添加到原型庫中,eat屬性就可以共享了(李四說“太好了,我也可以吃飯了o(≧v≦)o~~”)。這個屬性和方法(方法類似處理)的問題就解決了,那如果出現兩個對象Person和Student,Person還是具有構造函數的name屬性和用prototype添加的eat屬性,我想讓Student繼承Person中所有的屬性和方法,請看第三點。
三、prototype繼承實例
首先創建Person和Student構造函數(為了方便看,構造函數和實例輸出一起寫了)。
function Person(name){ this.name = name; } Person.prototype.eat = "food"; function Student(name,eat){ Person.apply(this,arguments); /* 繼承構造函數,即私有屬性 */ } var s1 = new Student("王五","food"); console.log(s1.name); /* 輸出 王五 */ console.log(s1.eat); /* undefined */
Student要繼承Person中的屬性,添加Person.apply(this,arguments) (標注:apply中this表示實例化的對象s1,arguments是new Student()中的參數,這是系統執行的),表示Student繼承Person中屬性。創建一個實例s1,s1輸出正常,為什么s1.eat輸出undefined?Person中不是已經添加了eat屬性嗎?為什么還不行呢?我找啊找,最終發現原來是Person.apply(this,arguments)只能繼承構造函數中的屬性,哎,真是弱爆了。那我想要繼承原型中的屬性怎么辦?那容易,請看下面代碼。
Student.prototype = new Person(); /* 繼承原型,即共享屬性 */ var s1 = new Student("王五","food"); console.log(s1.name); /* 輸出 王五 */ console.log(s1.eat); /* 輸出 food */
添加一個Student.prototype = new Person()就可以了。
這里做一個特別解釋:
Student具有prototype這個屬性的原因是因為它是一個function一個構造函數,前面我提到過,這個是構造函數特有的屬性。如果student是這樣的。
var student = { name: "張三" }
那就要報錯了,說student不是一個function。這個是大家特別注意的。
還有為什么要new Person()呢,這個和java中類似,但是在javascript中只針對於構造函數(構造函數中函數命名和類命名類似,首字母要大寫),其他不需要new。
有哪里講解的不好或者是不正確的地方,希望大家能第一時間反饋給我,希望和大家共同進步,謝謝。