【12-30】手寫繼承

function Person(name) {
    this.name = name
  }
  Person.prototype.say = function() {
    console.log(`你好,我是 ${this.name}`)
  }

// 嘗試定義一個(gè)子類,來繼承 Person
  function Student(name, id){
    Person.call(this, name) // 調(diào)用父類構(gòu)造函數(shù)
    this.id = id
  }
Student.prototype.fun = function(){
    console.log(`你好,我是 ${this.name},我的學(xué)號是${this.id}`);
}
  let s = new Student('瑪麗','1534543')
 s.fun()//你好,我是 瑪麗,我的學(xué)號是1534543
 s.toString()
//   s.say() s的proto中找,proto指向器構(gòu)造函數(shù)的prototype,原型是一個(gè)對象也有proto,proto又可以指向構(gòu)造函數(shù)的prototype
console.log(Student.prototype.__proto__===Object.prototype);//true

s.fun()//你好,我是 瑪麗,我的學(xué)號是1534543
說明Person的屬性成功被繼承了
但是這個(gè)時(shí)候的say()方法未定義,s.say() s的proto中找,proto指向器構(gòu)造函數(shù)的prototype,這
原型是一個(gè)對象也有proto,proto又可以指向構(gòu)造函數(shù)的prototype,這個(gè)時(shí)候應(yīng)該是指向Object,身上并沒say方法
加上這句話

Student.prototype=Person.prototype;

找不到say時(shí),就 proto->Student.prototype->Object.prototype現(xiàn)在把指向改成了
但是!如果這個(gè)時(shí)候 Student 想要給自己的 prototype 加一個(gè)新方法,怎么辦?我們知道因?yàn)橹皇菑?fù)制了地址,如果修改了 Student.prototype,Person.prototype 也將被修改,這顯然是我們不愿意看到的。
Person.prototype,找到了了Person上的say方法,但是Student.prototype.fun上的fun找不到了
再進(jìn)行更改:

Student.prototype.__proto__ = Person.prototype

改成這樣,就會先去prototype尋找,沒找到的話再順著proto往上找到Person

是不是看起來有點(diǎn)眼熟?
Array.prototype.__proto__ === Object.prototype // true
這就是原型鏈!這就是我們所說的繼承!是不是有點(diǎn)感覺了?
當(dāng)然,剛才也說了,我們最好用下面這種寫法:
Student.prototype = Object.create(Person.prototype)
復(fù)制代碼回顧一下到現(xiàn)在我們做了什么?

首先我們通過 call 父級構(gòu)造函數(shù),來實(shí)現(xiàn)屬性的繼承,有了 姓名
然后我們通過建立原型鏈,來實(shí)現(xiàn)方法的繼承,我們的 小明 可以 自我介紹 了

看似已經(jīng)結(jié)束,但是實(shí)際上還有一個(gè)隱藏的 Bug,我們接下來來解決這個(gè) Bug。

解決 constructor 的問題

細(xì)心的你會發(fā)現(xiàn)(我們在最開始也說過了),我們的對象實(shí)例和構(gòu)造函數(shù)中是有一個(gè) constructor 屬性的,比如:

const arr = [1, 2]
arr.__proto__.constructor === Array // true
Array.prototype.constructor === Array // true

但是,Student.prototype 中的 constructor 被剛才的那一番操作給搞沒了,我們需要把它弄回來:
Student.prototype.constructor = Student
這樣就完成了一波類的繼承。

總結(jié)

  function Person(name) {
    this.name = name
  }
  Person.prototype.say = function() {
    console.log(`你好,我是 ${this.name}`)
  }

// 嘗試定義一個(gè)子類,來繼承 Person
  function Student(name, id){
    Person.call(this, name) // 調(diào)用父類構(gòu)造函數(shù)
    this.id = id
  }
Student.prototype.fun = function(){
    console.log(`你好,我是 ${this.name},我的學(xué)號是${this.id}`);
}
// Student.prototype=Person.prototype;
Student.prototype.__proto__ = Person.prototype;
Student.prototype.constructor = Student
  let s = new Student('瑪麗','1534543')
  let p = new Person('張三')
  s.say()
  s.fun()

用 class 繼承

既然他本身就是語法糖,我個(gè)人認(rèn)為沒必要搞那么細(xì),其實(shí)本質(zhì)跟上面的使用原型鏈的繼承是一樣的,搞清楚是怎么寫的就好啦:

// 定義父類
class Person {
  constructor(name) { // 定義屬性
    this.name = name
  }
  say() { // 定義方法
    console.log(`你好,我是 ${this.name}`)
  }
}

// 定義子類
class Student extends Person {
  constructor(name, id) {
    super(name) // 這里的 姓名 兩個(gè)字要與父類中的一樣,繼承屬性和方法
    this.id = id // 定義新屬性
  }
  fun() { // 定義新方法
    console.log(`我的學(xué)號是 ${this.id}`)
  }
}



let s = new Student('小紅', 345678)
s.say() // 你好,我是 小紅
s.fun() // 我的學(xué)號是 345678

不同點(diǎn)可以看這篇文章

  1. class類內(nèi)部定義的所有方法都是不可枚舉的。這點(diǎn)和ES5行為不一致。

  2. 類和模塊的內(nèi)部默認(rèn)使用嚴(yán)格模式,所以不需要使用use strict指定運(yùn)行模式。

  3. 類必須使用 new 來調(diào)用,否則會報(bào)錯。這是他跟普通構(gòu)造函數(shù)的一個(gè)主要區(qū)別,后者不用 new 也可以執(zhí)行。

  4. 類內(nèi)部不存在變量提升,這一點(diǎn)與ES5完全不同。

  5. class繼承可以實(shí)現(xiàn)原生構(gòu)造函數(shù)的繼承,而ES5不可以。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概述 本篇主要講述構(gòu)造函數(shù)和繼承 構(gòu)造函數(shù) 編程 編程主要分為函數(shù)式編程和面向?qū)ο缶幊?函數(shù)式編程 ==> 推崇函...
    bowen_wu閱讀 447評論 0 0
  • Javascript中的‘類’ Javascript中并沒有嚴(yán)格意義上的類。ES5中通過使用首字母大寫的方法來模擬...
    softbone閱讀 405評論 0 0
  • 原型 簡單創(chuàng)建一個(gè)構(gòu)造函數(shù)與實(shí)例: Person 構(gòu)造函數(shù)person 是 Person 的一個(gè)實(shí)例對象 inst...
    月光在心中閱讀 702評論 0 5
  • 一,JavaScript的書寫格式 1.行內(nèi)腳本:寫在HTML標(biāo)簽內(nèi)部,通過一個(gè)屬性節(jié)點(diǎn)來添加,不推薦使用,例如“...
    劉遠(yuǎn)舟閱讀 572評論 0 0
  • this部分鏈接 原型鏈相關(guān)問題 問題7:有如下代碼,解釋Person、 prototype、proto、p、co...
    鴻鵠飛天閱讀 388評論 0 0

友情鏈接更多精彩內(nèi)容