【前言】
近來因為講課需要赫舒,涉及到使用JavaScript中的繼承翼馆,但發(fā)現(xiàn)遇上不懂的同學(xué),無法用一句話帶過启具,因為周邊涉及的知識點比較多本讥,因此決定系統(tǒng)的來說一說,我先簡單用一點圖來描述什么是繼承富纸。(不懂的同學(xué)可以先忽略英文)
請先忽略prototype等看不懂的單詞囤踩,可以看到祖宗改變就能影響后代,這樣也就讓我們能改一處晓褪,多出發(fā)生變化,減輕了工作量综慎,提高了效率涣仿。
【繼承的思路】
總的來說繼承可以理解為設(shè)置屬性或功能的多復(fù)用,那么大致有2條路子實現(xiàn)該功能。
1:祖宗構(gòu)造函數(shù)的原型好港,其是創(chuàng)建對象時參照的模板愉镰,所有實例共享該原型對象的是屬性及函數(shù)。
2:祖宗構(gòu)造函數(shù)本身的復(fù)用钧汹,在子孫構(gòu)造函數(shù)內(nèi)部調(diào)用祖宗的構(gòu)造函數(shù)丈探,因此執(zhí)行了祖宗的構(gòu)造方法,從而子孫享有祖宗構(gòu)造過程拔莱。
【構(gòu)造函數(shù)繼承】
重點就是子類調(diào)用父類構(gòu)造函數(shù)來創(chuàng)建對象
// 人類functionPeople(){this.description ='人類';}// 學(xué)生functionStudent(){// 調(diào)用People函數(shù)碗降,改變this指向People.call(this);}vars =newStudent();s.description;// 人類
【原型繼承】
重點是子類使用父類原型來共享
// 人類functionPeople(){}People.prototype.description ='人類';varp =newPeople();// 學(xué)生functionStudent(){}// 原型繼承Student.prototype = People.prototype;vars =newStudent();s.description;// 人類p.description;// 人類
【出現(xiàn)問題】
我們看到上面例子會帶來一個很簡單的問題,那就是 Student.prototype和People.prototype是同一個原型塘秦,當我們?nèi)ジ膭尤魏我粋€原型的時候讼渊,將會影響Student和People的實例。試想People改動影響Student也許我們覺得還ok尊剔,可是反之爪幻,就感覺不對了。
【原型:父類實例繼承】
我們知道 new 父類()得到的結(jié)果是和父類原型息息相關(guān)的须误,因此為了避免Student.prototype和People.prototype是同一個對象挨稿,而new People()創(chuàng)建的對象是根據(jù)People.prototype來的,所以我們用一個父類的實例來代替原型京痢,從而避免上述問題
// 人類functionPeople(){}People.prototype.description ='人類';// 學(xué)生functionStudent(){}// 原型繼承Student.prototype =newPeople();vars =newStudent();s.description;// 人類
【組合繼承】
但同時叶组,我們需要父類構(gòu)造函數(shù)的執(zhí)行獲取其他屬性,就需要使用到組合繼承的方式了历造,也就是【原型繼承】+【構(gòu)造函數(shù)繼承】
// 人類functionPeople(newProps){this.newProps = newProps;}People.prototype.description ='人類';// 學(xué)生functionStudent(){// 調(diào)用父類構(gòu)造函數(shù)People.call(this);}// 原型繼承Student.prototype =newPeople();vars =newStudent();s.description;// 人類s.newProps;// xxx
這里稍有不慎你可能會看到
都是因為沒有傳遞參數(shù)的問題甩十,那原型上這個undefine顯得不好看,而我們傳遞該值又顯得沒有意義吭产,從內(nèi)存角度來說侣监,我們只是需要原型而不是需要走構(gòu)造函數(shù)呀。
【新建對象繼承】
// 人類functionPeople(newProps){this.newProps = newProps;}People.prototype.description ='人類';// 學(xué)生functionStudent(){// 調(diào)用父類構(gòu)造函數(shù)People.call(this);}// 原型繼承Student.prototype =Object.create(People.Prototype);vars =newStudent();s.description;// 人類s.newProps;// xxx
【總結(jié)】
JS中的繼承主要分為兩條線即兩種思路:
根據(jù)父類構(gòu)造函數(shù)
根據(jù)原型
由于僅靠構(gòu)造函數(shù)構(gòu)造出的實例臣淤,我們針對方法不太會使用this.fn = function(){}來浪費內(nèi)存橄霉,因此會使用到原型,而原型又存在相同對象指向的問題邑蒋,因此創(chuàng)建一個新的對象姓蜂,然后新對象可能需要參數(shù),會導(dǎo)致子類原型看起來不好看医吊,這樣我們使用Object.create(父類原型)钱慢,同時,如果父類構(gòu)造函數(shù)內(nèi)的屬性我們需要卿堂,那么還需要組合起來調(diào)用束莫。
推薦學(xué)習(xí):Web職場加油班——JS精講:http://xue.ujiuye.com/class-102355/