利用原型鏈和借用構(gòu)造函數(shù)實現(xiàn)繼承

原型鏈繼承

原型鏈是實現(xiàn)繼承的主要方法,其基本思想是利用原型讓一個引用類型繼承另外一個引用類型的屬性和方法。
在介紹原型鏈之前,需要了解掌握以下幾點內(nèi)容:
構(gòu)造函數(shù)、原型對象、實例對象之間的關(guān)系:
1. 每一個構(gòu)造函數(shù)都有一個原型對象,原型對象都包含有一個指向其構(gòu)造函數(shù)的指針(constructor);
2. 實例對象包含一個指向原型對象的內(nèi)部指針(_ proto _);
3. 每一個構(gòu)造函數(shù)都有一個prototype屬性,用來指向它的原型對象

構(gòu)造函數(shù)、原型對象、實例對象三者之間的關(guān)系.png

如果讓原型對象等于另一個類型的實例,此時,原型對象將包含一個指向另一個原型的指針,相應(yīng)地,另一個原型中也包含著一個指向另一個構(gòu)造函數(shù)的指針。如此下去,每一個原型對象都是下一個構(gòu)造函數(shù)的實例對象,這樣就構(gòu)成了實例與原型的鏈條,就是所謂的原型鏈。

原型鏈示例.png
function Animal() {
            this.name = "animal";
            this.age  =  18;
            this.say  = function() {
                console.log("hellow");
            } 
        }
        //給原型對象添加方法
        Animal.prototype.run = function() {
            console.log("running");
        }
function Person() {
            this.name = "person";
        }
/*******************未構(gòu)建原型鏈之前實例的per對象*****************************************/
        // var per = new Person;
        // console.log(per);
        // per.say();// is not a function
        //因為沒有構(gòu)建原型鏈,所以Person實例的per對象中沒有say()方法
/*******************未構(gòu)建原型鏈之前實例的per對象*****************************************/
        //解決方法:
        // 1.利用原型鏈的繼承關(guān)系,構(gòu)建原型鏈
        // console.log(per.constructor);//Person
        // console.log(Person.prototype.constructor);//Person

        Person.prototype = new Animal();//原型鏈的核心

        //此時Person的原型對象的constructor屬性指向的是Animal了
        // console.log(per.constructor);//Person
        // console.log(Person.prototype.constructor);//Aniaml
        // 為了保證原型對象的constructor指向不變
        Person.prototype.constructor = Person;//(可以不寫,不會對代碼運行造成影響)
        // 構(gòu)建好原型鏈之后再創(chuàng)建per對象!!!;
        // 特別注意:要想子類構(gòu)造函數(shù)實例的對象擁有父級的方法(say()),必須先搭建原型鏈關(guān)系即:Person.prototype = new Animal();,再實例對象。
         var per = new Person();
         console.log(per.name);//animal
         per.say();//hellow  對比未構(gòu)建原型鏈之前的per.say()//pre is not defined
         per.run();//running;

總結(jié):

優(yōu)點:可以繼承父級的所有方法;
缺點:
1.創(chuàng)建子類型的實例時不能向超類型的構(gòu)造函數(shù)傳遞參數(shù)
2.子類實例共享父類引用屬性的問題。

借用構(gòu)造函數(shù)法實現(xiàn)繼承

基本思想就是在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)。
介紹借用構(gòu)造函數(shù)之前需要掌握以下幾點
每個函數(shù)都有call()和apply()方法
Function.apply(obj,[參數(shù)2,參數(shù)3,參數(shù)4...])等同于Function.apply(obj,arguments)
obj:這個對象將代替Function類里this對象
[]:這個是數(shù)組,它將作為參數(shù)傳給Function
Function.call([obj[,參數(shù)2[, 參數(shù)3[,參數(shù)4 [,.argN]]]]]) (我個人看著這個很別扭,簡單說就是,將上面的數(shù)組集合拆為單個的參數(shù)書寫)
Function.call(obj,參數(shù)2,參數(shù)3,參數(shù)4,...)

 function Animal(name,age) {
            this.name = name;
            this.age  = age ;
            this.say  = function() {
                console.log("hellow");
            } 
        }
        //給原型對象添加方法
        Animal.prototype.run = function() {
            console.log("running");
        }
 function Person(name,age) {
            Animal.call(this,name,age);//核心關(guān)鍵
            // Animal.apply(this,[name,age]);
            // Animal.apply(this,arguments);
        }
         var per    =  new  Person();
         animal.say.call(per);//只傳遞了一個對象參數(shù)
         Animal.call(per,"李明",18);//傳遞了三個參數(shù):參數(shù)1:對象;參數(shù)2:“李明”;參數(shù)3:18
         console.log(per);
         Animal.call(per,"王磊",21)
         console.log(per);
結(jié)果.jpg

總結(jié):

call()與apply()沒有太大區(qū)別,只是參數(shù)傳遞方式不同
優(yōu)點:
1.解決了子類實例共享父類引用屬性的問題
2.創(chuàng)建子類實例時,可以向父類構(gòu)造函數(shù)傳參,
缺點:
無法實現(xiàn)函數(shù)復(fù)用,每個子類實例都持有一個新的fun函數(shù),太多了就會影響性能,內(nèi)存爆炸(參考別人的,自己也不太清楚)。

補充:

實際經(jīng)常將原型鏈和借用構(gòu)造函數(shù)結(jié)合起來使用,即組合繼承。其背后的思想是使用原型鏈實現(xiàn)原型屬性和方法的繼承,而通過借用構(gòu)造函數(shù)來實現(xiàn)實例屬性的繼承。這樣,即通過在原型上定義方法實現(xiàn)了函數(shù)復(fù)用,用能夠保證每個實例都有自己的屬性。
關(guān)于apply()還有一些其他巧妙用法

apply的一些其他巧妙用法

在調(diào)用apply方法的時候,第一個參數(shù)是對象,第二個參數(shù)是一個數(shù)組集合,但是在調(diào)用父級構(gòu)造函數(shù)的時候,它需要的不是一個數(shù)組,但是,為什么他給我一個數(shù)組我仍然可以解析成一個個參數(shù)呢?這就是apply的一個巧妙的用法:apply()可以將一個數(shù)組默認的轉(zhuǎn)換成為一個參數(shù)列表
這個如果讓我們用程序來實現(xiàn)將數(shù)組的每一項轉(zhuǎn)換成參數(shù)列表可能會費點功夫,借助apply的這點特性,就方便多了
var max = Math.max.apply(null,[1,2,3,4,6,8,0]); console.log(max);
更多關(guān)于apply的詳細介紹

后記:

這是自己第一次使用markdown寫的筆記,你能想象我寫這篇文章用一天的時間么?把腦袋里的想法用文字表達出來,對于我這個不善表達的人是多么不容易呀。17年,一起加油。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內(nèi)容