js中繼承的7種方法

1.原型鏈繼承

核心思想是構(gòu)造函數(shù)欠痴,實(shí)例對(duì)象以及原型這三者的關(guān)系

// 原型鏈繼承
        function Person(){
            this.name = "張大寶";
        }
        Person.prototype.getName = function(){
            console.log(this.name);
        }
        function Student(){           
        }
        Student.prototype = new Person();
        var student = new  Student();
        student.getName(); // 張大寶

缺點(diǎn):
1.原型鏈中引用類型的屬性會(huì)被所有實(shí)例共享的,即所有實(shí)例對(duì)象使用的是同一份數(shù)據(jù)单刁,會(huì)相互影響。

function Person(){
            this.colors = ["red", "green", "pink"];
        }
        function Student(){
        }
        Student.prototype = new Person();
        var a1 = new Student();
        var a2 = new Student();
        a1.colors.push("white");
        console.log(a2.colors);    //"red", "green", "pink" ,"white"

2.在創(chuàng)建子類的實(shí)例時(shí)糕簿,不能向超類傳參(無(wú)法向父級(jí)構(gòu)造函數(shù)傳參)

2.借用構(gòu)造函數(shù)(經(jīng)典繼承)

核心思想是:在子級(jí)構(gòu)造函數(shù)中調(diào)用父級(jí)構(gòu)造函數(shù)。
如何實(shí)現(xiàn)在一個(gè)構(gòu)造函數(shù)中調(diào)用另一個(gè)函數(shù)?——call()和apply()

// 借用構(gòu)造函數(shù)繼承(經(jīng)典繼承)
        function Person(){
            this.name = "張大寶";
            this.colors = ["red", "green", "pink"]];
        }
        Person.prototype.getName = function(){
            console.log(this.name);
        }
        function Student(){
            Person.call(this);
        }
        var a1 = new Student();
        var a2 = new Student();
        a1.colors.push("white");
        console.log(a1.name);
        console.log(a1.colors); // ["red", "green", "pink", "white"]
        console.log(a2.colors); // ["red", "green", "pink"]

優(yōu)點(diǎn):
1.避免了引用類型的屬性被所有實(shí)例共享
2.可以在子類中向超類傳參
缺點(diǎn):
1.只能繼承父類的私有的屬性和方法,不能繼承原型上的屬性和方法;
2.無(wú)法實(shí)現(xiàn)構(gòu)造函數(shù)的復(fù)用术奖,每個(gè)子類都有父類實(shí)例函數(shù)的副本,影響性能轻绞,代碼會(huì)臃腫采记。

3.組合繼承

組合繼承 = 原型鏈 + 借用構(gòu)造函數(shù)。取其長(zhǎng)避其短:共享的用原型鏈铲球,各自的借用構(gòu)造函數(shù)
核心思路是使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承挺庞,而通過(guò)借用構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承晰赞,這樣稼病,既通過(guò)在原型上定義方法實(shí)現(xiàn)了函數(shù)復(fù)用,又能保證每個(gè)實(shí)例都有它自己的屬性掖鱼。

function Parent(name){
            this.name = name;
            this.colors = ["red", "green", "pink"];
        }
        Parent.prototype.getName = function(){
            console.log(this.name);
        }
        function Student(name,age){
            Parent.call(this,name);// 第二次調(diào)用 Parent()
            this.age = age;
        }
        Student.prototype = new Parent(); // 第一次調(diào)用 Parent()
        var a1 = new Child("張大寶",18);
        var a2 = new Child("張小寶",19);
        a1.getName(); //張大寶
        a2.getName();// 張小寶
        console.log(a1.age); // 18
        console.log(a2.age); // 19
        child1.colors.push("white");
        console.log(a1.colors);  // ["red", "blue", "green", "white"]
        console.log(a2.colors); // ["red", "blue", "green"]
        console.log(a1 instanceof Child); // true
        console.log(a2 instanceof Parent); // true

優(yōu)點(diǎn):融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn)然走,是JavaScript中最常用的繼承模式
缺點(diǎn):調(diào)用了兩次父類構(gòu)造函數(shù)
(組合繼承最大的問(wèn)題是無(wú)論什么情況下,都會(huì)調(diào)用兩次超類型構(gòu)造函數(shù):一次是在創(chuàng)建子類型原型的時(shí)候戏挡,另一次是在子類型構(gòu)造函數(shù)內(nèi)部)

4.原型式繼承

在createObj()函數(shù)內(nèi)部,先創(chuàng)建了一個(gè)臨時(shí)性的構(gòu)造函數(shù),然后將傳入的對(duì)象作為這個(gè)構(gòu)造函數(shù)的原型,最后返回了這個(gè)臨時(shí)類型的一個(gè)新實(shí)例.從本質(zhì)上講,createObj()對(duì)傳入其中的對(duì)象執(zhí)行了一次淺復(fù)制.

// 原型式繼承
function createObj(o){
    function F(){}
    F.prototype = o;
    return new F()
}
var person = {
    name:"張大寶",
    colors:["red","pink","green"]
}
var a1 = createObj(person)
a1.name = "張小寶"
a1.colors.push = "white"
console.log(a1.name)    // 張小寶
console.log(a1.colors)    // "red","pink","green","white"
var a2 = createObj(person)
console.log(a2.name)    // 張大寶
console.log(a2.colors)     // "red","pink","green","white"

找對(duì)象上的屬性時(shí)芍瑞,總是先找實(shí)例上對(duì)象,沒(méi)有找到的話再去原型對(duì)象上的屬性褐墅。實(shí)例對(duì)象和原型對(duì)象上如果有同名屬性拆檬,總是先取實(shí)例對(duì)象上的值
缺點(diǎn): 包含引用類型的屬性值始終都會(huì)共享相應(yīng)的值, 這點(diǎn)跟原型鏈繼承一樣
ECMAScript5通過(guò)新增Object.create()方法規(guī)范化了原型式繼承妥凳,這個(gè)方法接收兩個(gè)參數(shù):
一個(gè)用作新對(duì)象原型的對(duì)象和一個(gè)作為新對(duì)象定義額外屬性的對(duì)象竟贯。
上面的代碼還可以這樣寫:
在傳入一個(gè)參數(shù)的情況下,Object.create()與createObj()方法的行為相同

var person = {
    name:"張大寶",
    colors:["red","pink","green"]
}
var a1 = Object.create(person)
a1.name = "張小寶"
a1.colors.push = "white"
console.log(a1.name)    // 張小寶
console.log(a1.colors)    // "red","pink","green","white"
var a2 = Object.create(person)
console.log(a2.name)    // 張大寶
console.log(a2.colors)     // "red","pink","green","white"

Object.create()方法的第二個(gè)參數(shù)與object.defineProperties()方法的第二個(gè)參數(shù)格式相同:每個(gè)屬性都是通過(guò)自己的描述符定義的

var a1 = Object.create(person,{
  name:{
        value:"張二寶"
});
console.log(a1.name);  //  張二寶

5.寄生式繼承

在原型式繼承的基礎(chǔ)上逝钥,在函數(shù)內(nèi)部豐富對(duì)象

function fun(obj) {
    function Son() { };
    Son.prototype = obj;
    return new Son();
}
function JiSheng(obj) {
    var clone = fun(obj);    //  通過(guò)調(diào)用函數(shù)創(chuàng)建一個(gè)新對(duì)象
    clone.Say = function () {    //  以某種方式來(lái)增強(qiáng)這個(gè)對(duì)象
        console.log('我是新增的方法');
    }
    return clone;    //  返回這個(gè)對(duì)象
}
var parent = {
    name: '張三'
}
var parent1 = JiSheng(parent);
var parent2 = JiSheng(parent);
console.log(parent2.Say==parent1.Say);// false

優(yōu)缺點(diǎn):跟借用構(gòu)造函數(shù)類似屑那,調(diào)用一次函數(shù)就得創(chuàng)建一遍方法,無(wú)法實(shí)現(xiàn)函數(shù)復(fù)用艘款,效率較低持际。

6.寄生組合式繼承

利用組合繼承和寄生繼承各自優(yōu)勢(shì)
寄生組合式繼承,是集寄生式繼承和組合繼承的有點(diǎn)與一身哗咆,主要是通過(guò)借用構(gòu)造函數(shù)來(lái)繼承屬性蜘欲,通過(guò)原型鏈的混成形式來(lái)繼承方法。它的缺點(diǎn)是兩次調(diào)用父級(jí)構(gòu)造函數(shù)晌柬,一次是在創(chuàng)建子級(jí)原型的時(shí)候姥份,另一次是在子級(jí)構(gòu)造函數(shù)內(nèi)部呜叫,那么我們只需要優(yōu)化這個(gè)問(wèn)題就行了,即減少一次調(diào)用父級(jí)構(gòu)造函數(shù)殿衰,正好利用寄生繼承的特性朱庆,繼承父級(jí)構(gòu)造函數(shù)的原型來(lái)創(chuàng)建子級(jí)原型。

function JiSheng(son,parent) {
    var clone = Object.create(parent.prototype);//創(chuàng)建對(duì)象
    son.prototype = clone;      //指定對(duì)象
    clone.constructor = son;     //增強(qiáng)對(duì)象
}
function Parent(name){
    this.name = name;
    this.type = ['JS','HTML','CSS'];
}
Parent.prototype.Say=function(){
    console.log(this.name);
}
function Son(name){
    Parent.call(this,name);
}
JiSheng(Son,Parent);
son1 = new Son('張三');
son2 = new Son('李四');
son1.type.push('VUE');
son2.type.push('PHP');
console.log(son1.type);//['JS','HTML','CSS','VUE']
console.log(son2.type);//['JS','HTML','CSS','PHP']
son1.Say();//張三
son2.Say();//李四

優(yōu)缺點(diǎn):組合繼承優(yōu)點(diǎn)闷祥、寄生繼承的優(yōu)點(diǎn)娱颊,目前JS繼承中使用的都是這個(gè)繼承方法

7.ES6里的extends繼承

class People{
        constructor(name){
            this.name = name;
        }
        walk(){
            console.log(this.name + "會(huì)走路");
        }
    }
    class Student extends People{
        constructor(name){
            super();//調(diào)用了父類的構(gòu)造函數(shù)
            this.name = name;
        }

    }
    var ZhangDaoBao = new Student("張大寶");
    ZhangDaoBao.walk();//張大寶會(huì)走路
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凯砍,隨后出現(xiàn)的幾起案子箱硕,更是在濱河造成了極大的恐慌,老刑警劉巖悟衩,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剧罩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡座泳,警方通過(guò)查閱死者的電腦和手機(jī)惠昔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)挑势,“玉大人镇防,你說(shuō)我怎么就攤上這事〕北ィ” “怎么了来氧?”我有些...
    開(kāi)封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)香拉。 經(jīng)常有香客問(wèn)我啦扬,道長(zhǎng),這世上最難降的妖魔是什么凫碌? 我笑而不...
    開(kāi)封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任扑毡,我火速辦了婚禮,結(jié)果婚禮上证鸥,老公的妹妹穿的比我還像新娘僚楞。我一直安慰自己,他們只是感情好枉层,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布泉褐。 她就那樣靜靜地躺著,像睡著了一般鸟蜡。 火紅的嫁衣襯著肌膚如雪膜赃。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天揉忘,我揣著相機(jī)與錄音跳座,去河邊找鬼端铛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛疲眷,可吹牛的內(nèi)容都是我干的禾蚕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼狂丝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼换淆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起几颜,我...
    開(kāi)封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤倍试,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蛋哭,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體县习,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年谆趾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了躁愿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡棺妓,死狀恐怖攘已,靈堂內(nèi)的尸體忽然破棺而出炮赦,到底是詐尸還是另有隱情怜跑,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布吠勘,位于F島的核電站性芬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏剧防。R本人自食惡果不足惜植锉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望峭拘。 院中可真熱鬧俊庇,春花似錦、人聲如沸鸡挠。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拣展。三九已至彭沼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間备埃,已是汗流浹背姓惑。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工褐奴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人于毙。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓敦冬,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親唯沮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匪补,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348