JS中的繼承方式:

1.1 原型鏈繼承

  • 原型繼承: 將子類(lèi)B的原型對(duì)象 重寫(xiě)成父類(lèi)A的一個(gè)實(shí)例。

B.prototype = new A();
把父類(lèi)共有屬性和私有屬性變成子類(lèi)的公有屬性

function A() {
}
A.prototype.age = 19;
A.prototype.say = function () {
   console.log('來(lái)自A類(lèi)原型的say方法')
};
function B() {}
B.prototype = new A();  //把B類(lèi)的原型改寫(xiě)成一個(gè)A類(lèi)的實(shí)例逝她;
let b = new B();
console.log(b);
console.log(b.__proto__);  {text: 'xxx', __proto__....}
console.log(b.age);
console.log(b.say);

把B的原型改寫(xiě)成A類(lèi)的一個(gè)實(shí)例卵迂,此時(shí)通過(guò) b.age 訪問(wèn)b的age屬性坎炼,首先在私有屬性中查找扳炬,私有屬性中沒(méi)有age屬性,接著去b所屬類(lèi)的原型(B.prototype)上查找序芦,此時(shí)原型對(duì)象是A的實(shí)例對(duì)象愧沟,在原型對(duì)象也沒(méi)有age屬性蔬咬,然后通過(guò)原型對(duì)象的proto就找到了A.prototype上,A的prototype上有age屬性

  • 原型繼承是把子類(lèi)公有的屬性和私有的屬性都變成了子類(lèi)私有的屬性沐寺;
  • 缺點(diǎn):改寫(xiě)子類(lèi)的原型對(duì)象林艘,會(huì)導(dǎo)致子類(lèi)原型對(duì)象上的constructor屬性被改寫(xiě),需要重新指定繼承后的constructor混坞;

1.2 借用構(gòu)造函數(shù)繼承

借用構(gòu)造函數(shù):把父類(lèi)當(dāng)做普通函數(shù)狐援,在子類(lèi)的函數(shù)體中call執(zhí)行父類(lèi)的函數(shù);

function A() {
   this.a = 'aa';
   this.say = function () {
      console.log('A say');
   }
}
A.prototype.public = 'public';
function B() {
   A.call(this);  //this是B類(lèi)的一個(gè)實(shí)例究孕,A.call(this) 的意思是把A中的this就該成B的實(shí)例(而在B的構(gòu)造函數(shù)中this就是B的實(shí)例)這樣在A中通過(guò)this.xxx = xxx 的方式添加的屬性都會(huì)添加到B的實(shí)例身上啥酱。
}
let b = new B();
console.log(b);  {a: 'aa', say: fun.....}
let b2 = new B();
console.log(b2.say === b.say);  false;

借用構(gòu)造函數(shù)繼承:

  • 把父類(lèi)當(dāng)做普通函數(shù),在子類(lèi)的函數(shù)體里面蚊俺,通過(guò)call方法執(zhí)行 A.call(this)
  • call方法是用來(lái)修改this指向的,這樣一來(lái)就把A中的this修改成了b的實(shí)例逛万;在函數(shù)A中通過(guò)this.xxx = xxx 添加的屬性都添加到了B的實(shí)例身上泳猬;
  • 特點(diǎn):只能把父類(lèi)的私有屬性和方法繼承為子類(lèi)的私有屬性和方法;

.3 組合繼承

組合繼承:原型鏈繼承 + 借用構(gòu)造函數(shù)繼承

  • 原型鏈繼承:把父類(lèi)私有的和共有的繼承為子類(lèi)公有的宇植;
  • 借用構(gòu)造函數(shù)繼承:把父類(lèi)私有的繼承為子類(lèi)私有的
   this.a = '私有的'
}
A.prototype.text = '公有';
A.prototype.say = function () {
   console.log('A公有的say方法')
};
function B() {
   A.call(this);  //借用構(gòu)造函數(shù)繼承得封,繼承父類(lèi)私有的
}
B.prototype = new A();  //原型鏈繼承,繼承父類(lèi)私有和公有的屬性指郁;
B.prototype.constructor = B;
let b = new B();
console.log(b.text);  公有的
console.log(b.a);  私有的
  • 組合繼承也并非沒(méi)有缺點(diǎn)忙上,組合繼承會(huì)把父類(lèi)的私有繼承兩次,一份在借用構(gòu)造函數(shù)繼承時(shí)成為私有的闲坎,而另一份是在原型繼承時(shí)成為公有的疫粥;

1.4 原型式繼承

原型式繼承:把父類(lèi)的公有屬性繼承為子類(lèi)的公有屬性;

創(chuàng)建一個(gè)新的對(duì)象腰懂,并且新對(duì)象的proto指向A.prototype梗逮,最后把這個(gè)新對(duì)象作為B類(lèi)的原型;

  • 創(chuàng)建一個(gè)對(duì)象绣溜,并且對(duì)象的proto 指向obj

Object.create(obj)

  • 原型式繼承示例
function A() {
   this.private = 'private私有';
}
A.prototype.public = 'public公有';
function B() {}
B.prototype = Object.create(A.prototype); // 創(chuàng)建一個(gè)指定原型的對(duì)象 創(chuàng)建一個(gè)對(duì)象慷彤,并且這個(gè)對(duì)象的__proto__ 指向A.prototype
B.prototype.constructor = B; // 原型式繼承同樣是修改B類(lèi)原型的指向,所以需要重新指定構(gòu)造函數(shù)
let b = new B();
console.log(b.public);

1.5 寄生組合式繼承

  • 寄生組合式繼承:原型式繼承 + 借用構(gòu)造函數(shù)繼承
function A() {
   this.private = '私有屬性';
}
A.prototype.public = '公有屬性';
function B() {
   A.call(this);  //借用構(gòu)造函數(shù)繼承
   this.name = 'b私有的';
}
 //原型式繼承:把父類(lèi)公有的 繼承為子類(lèi)實(shí)例公有的
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
let b = new B();  {name: '私有的', private: '私有屬性'}
console.log(b.private);  //繼承過(guò)來(lái)的私有屬性
console.log(b.public);  //繼承過(guò)來(lái)到的公有屬性

1.6 冒充對(duì)象繼承

冒充對(duì)象繼承:在子類(lèi)的構(gòu)造函數(shù)中生成一個(gè)父類(lèi)的實(shí)例,把父類(lèi)的這個(gè)實(shí)例進(jìn)行遍歷底哗,把屬性都添加子類(lèi)的實(shí)例上岁诉;

function A() {
   this.private = '私有屬性';
}
A.prototype.public = '公有屬性';
function B() {
   this.name = 'B私有的屬性';
   let tmp = new A();
   for (let key in tmp) {
      this[key] = tmp[key];
   }
}
let b = new B();
console.log(b);

1.7 ES6中的類(lèi)

ES5 一個(gè)函數(shù)就是一個(gè)類(lèi)
ES6 借鑒后端語(yǔ)言,增加了class關(guān)鍵字跋选,創(chuàng)建一個(gè)類(lèi)

  • ES5
function Teacher(name, age, subject) {
   this.name = name;
   this.age = age;
   this.subject = subject;
}
Teacher.motor = '傳道';
Teacher.prototype.teach = function () {
   console.log(this.name + this.age);
};
let t = new Teacher('mabin', 19, 'js');
  • ES6
class Teacher {
   constructor (name, age, subject) {
       //這里面通過(guò)this.xxx = xxx 是給實(shí)例添加私有屬性
      this.name = name;
      this.age = age;
      this.subject = subject;
   }
    //添加公有屬性
   teach () {
      console.log(this.name + this.age + this.subject);
   }
   // 添加靜態(tài)方法
   static motor = '傳授知識(shí)';
   static getMotor () {
      console.log('We are family');
   }
}
let t = new Teacher('馬賓賓', 21, 'HTML');
t.teach(); //馬賓賓21HTML
console.log(Teacher.motor); //傳授知識(shí)
Teacher.getMotor(); //We are family

1.7 ES6繼承

ES6繼承:extends關(guān)鍵字

class A {
   constructor (name, age) {
      this.name = name;
      this.age = age;
   }
    //公有方法(添加到原型上)
   say () {
      console.log(`${this.name} say`);
   }
}
 //ES6繼承時(shí)使用 extends 關(guān)鍵字實(shí)現(xiàn)繼承
class B extends A {  //B繼承A類(lèi)
   constructor (x, y, forName, forAge) {
       //注意:在使用ES6的extends關(guān)鍵字之前涕癣,必須使用super(); super表示父類(lèi)的構(gòu)造函數(shù)
      super(forName, forAge);  
      this.x = x;
      this.y = y;
   }
}
let b = new B('x', 'y', 'mabin', 18);
console.log(b); //{name: "mabin", age: 18, x: "x", y: "y"}
b.say(); //來(lái)自A類(lèi)原型的say方法
  • ES6的繼承原理是:寄生組合式繼承
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市野建,隨后出現(xiàn)的幾起案子属划,更是在濱河造成了極大的恐慌,老刑警劉巖候生,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件同眯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡唯鸭,警方通過(guò)查閱死者的電腦和手機(jī)须蜗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)目溉,“玉大人明肮,你說(shuō)我怎么就攤上這事$愿叮” “怎么了柿估?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)陷猫。 經(jīng)常有香客問(wèn)我秫舌,道長(zhǎng),這世上最難降的妖魔是什么绣檬? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任足陨,我火速辦了婚禮,結(jié)果婚禮上娇未,老公的妹妹穿的比我還像新娘墨缘。我一直安慰自己,他們只是感情好零抬,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布镊讼。 她就那樣靜靜地躺著,像睡著了一般平夜。 火紅的嫁衣襯著肌膚如雪狠毯。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天褥芒,我揣著相機(jī)與錄音嚼松,去河邊找鬼嫡良。 笑死,一個(gè)胖子當(dāng)著我的面吹牛献酗,可吹牛的內(nèi)容都是我干的寝受。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼罕偎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼很澄!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起颜及,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤甩苛,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后俏站,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體讯蒲,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年肄扎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了墨林。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡犯祠,死狀恐怖旭等,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衡载,我是刑警寧澤搔耕,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站痰娱,受9級(jí)特大地震影響弃榨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜猜揪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一惭墓、第九天 我趴在偏房一處隱蔽的房頂上張望坛梁。 院中可真熱鬧而姐,春花似錦、人聲如沸划咐。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)褐缠。三九已至政鼠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間队魏,已是汗流浹背公般。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工万搔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人官帘。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓瞬雹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親刽虹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子酗捌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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