ES 5 的構(gòu)造函數(shù)到 ES 6 的類

前言

雖然 ES 6 里引入了「類」這個(gè)概念,但是實(shí)際上 ES 6 的類只是 ES 5 的語(yǔ)法糖,本質(zhì)上還是一個(gè)「構(gòu)造函數(shù)」。本片筆記主要回顧 ES 5 通過(guò)構(gòu)造函數(shù)創(chuàng)建對(duì)象的一般方法,以及 ES 5 中類的繼承的一般方法;然后再介紹 ES 6 的寫法。

ES 5 中通過(guò)構(gòu)造函數(shù)創(chuàng)建對(duì)象和實(shí)現(xiàn)類繼承的一般方法

此部分涉及的內(nèi)容基本出自《JavaScript 高級(jí)程序設(shè)計(jì)(第 3 版)》第六章:「面向?qū)ο蟮某绦蛟O(shè)計(jì)」,里面介紹了不少種創(chuàng)建對(duì)象的方法和實(shí)現(xiàn)繼承的方法,這里我只從這些方法里各挑出一種最為廣泛使用的方法。首先是書上所謂的「組合使用構(gòu)造函數(shù)模式和原型模式」的創(chuàng)建對(duì)象的方法:

function Person(name, age, job) {
  this.name = name
  this.age = age
  this.job = job
  this.friends = [ 'Shelby', 'Court' ]
}

Person.prototype = {
  constructor: Person,
  sayName: function() {
    alert(this.name)
  }
}

Person.doSomething = function() {
  // do something
}
Person.aProperty = 'a property'

上面就是一個(gè)「類」:每個(gè)實(shí)例都擁有的各自不同的屬性放到構(gòu)造函數(shù)內(nèi)部,通過(guò) this 來(lái)初始化;所有實(shí)例都共享的方法放到構(gòu)造函數(shù)的 prototype 上;同時(shí)這個(gè)類本身還有一些只是自己所有的屬性或方法,別的面向?qū)ο笳Z(yǔ)言里稱之為靜態(tài)屬性(方法),這些靜態(tài)屬性直接掛到構(gòu)造函數(shù)本身上。通過(guò) new 操作符執(zhí)行這個(gè)函數(shù)就可以得到對(duì)應(yīng)的實(shí)例對(duì)象,所有的對(duì)象都有著自己的 name、agejob、friends 屬性,同時(shí)共享原型對(duì)象上的 sayName 方法。上面就是 ES 5 里一個(gè)類的基本創(chuàng)建方法,當(dāng)然如果要做的更好一點(diǎn)的話可以把 constructor 單獨(dú)用 Object.defineProperty 來(lái)寫,因?yàn)榘凑丈厦娴膶懛ㄋ?enumerable 的屬性將會(huì)是 true,而實(shí)際上是 false 的。

再來(lái)看看類的繼承,書上所謂「寄生組合式繼承」,其原理就是在子類的中調(diào)用父類,但是把 this 的值綁定成子類,然后在維護(hù)好原型鏈,將 Object.create(prototype) 賦值給子類的 prototype 同時(shí)將 prototypeconstructor 屬性指向子類本身:

function Teacher(name, age, subject) {
  Person.call(this, name, age, 'teacher')
  this.subject = subject
}

Teacher.prototype = Object.create(
  Person.prototype,
  {
    constructor: {
      value: Teacher,
      writable: true,
      configurable: true,
      enumerable: false
    },
    teach: function() {
      // teach something
    }
  }
)

上面的代碼就完成了 Teacher 類對(duì) Person 的繼承。

ES 6 中對(duì)應(yīng)的寫法

class Person {
  constructor(name, age, job) {
    this.name = name
    this.age = age
    this.job = job  
    this.friends = [ 'Shelby', 'Court' ]
  }
  sayName() {
    alert(this.name)
  }
  static soSomething() {
    // do something
  }
}

Person.aProperty = 'a property'

上面就是 ES 6 中類的寫法,看起來(lái)簡(jiǎn)潔很多了。但是好像對(duì)于靜態(tài)屬性,ES 6 目前還沒(méi)支持到這一步,所以也還是只能單獨(dú)寫。然后看下繼承:

class Teacher extends Person {
  constructor(name, age, subject) {
    super(name, age, 'teacher ')
    this.subject = subject
   }
   teach() {
      // teach something
    }
}

需要注意的是,當(dāng)子類想在 constructor 里引用 this 必須提前調(diào)用父類的構(gòu)造函數(shù) super() ,不然會(huì)報(bào)錯(cuò),這是因?yàn)?「ES 6 的繼承機(jī)制與上面 ES 5 的機(jī)制不同,ES 6 的機(jī)制是先由父類創(chuàng)建 this 值,然后再由子類的 contructor 去修改這個(gè)值」,這是我在 ES 6 相關(guān)的書上看到的,具體怎么個(gè)做法,暫時(shí)不得而知,不知道 Babel 會(huì)不會(huì)是按照 ES 6 的機(jī)制做的 transform。以上只是 class 的最基本的用法,剩下的一些特性下次詳細(xì)介紹。

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

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

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