使用es6新的class語法來體驗js的面向?qū)ο缶幊?/h2>

今天在看一本書,只有小小的一百多頁,半天快看完半本了,名字叫《學習JavaScript數(shù)據(jù)結(jié)構(gòu)預(yù)算法》.看下來的感受就是,短小精悍,適合復(fù)習一下大學學的數(shù)據(jù)結(jié)構(gòu)。
在讀到使用js實現(xiàn)棧的結(jié)構(gòu)的時候,看到它的寫法是之前的構(gòu)造函數(shù)繼承的寫法,突發(fā)奇想,想用es6的語法改寫一下試試,這是書上的寫法:

function Stack() {
  var items = []

  this.push = function(element) {
    items.push(element)
  }
  this.pop = function() {
    return items.pop()
  }
  this.peek = function() {
    return items[items.length - 1]
  }
  this.isEmpty = function() {
    return items.length === 0
  }
  this.size = function() {
    return items.length
  }
  this.clear = function() {
    items = []
  }
  this.print = function() {
    console.log(items.toString());
  }
}

算不上是類的寫法,只是在函數(shù)里定義了幾個方法,去修改items的值而已,新寫的寫法如下:

class Strack {
  constructor() {
    this.item = []
  }

  // 棧的壓入
  push(value) {
    this.item.push(value)
  }

  // 棧的彈出
  pop() {
    this.item.pop()
  }

  // 返回棧頂元素
  peek() {
    let lengthTemp = this.item.length
    return this.item[lengthTemp - 1]
  }

  // 判空
  isEmpty() {
    return this.item.length === 0
  }

  // remove all

  clear() {
    this.item = []
  }

  // sum all items
  size() {
    return this.item.length
  }
}

export default Strack

使用:

 const newStrack = new Strack()
    newStrack.push(1)
    newStrack.push(2)
    newStrack.push(3)
    newStrack.pop()
    console.log(newStrack, newStrack);
    console.log('newStrack is empty? : ', newStrack.isEmpty());

很簡單,但是沒有弄清楚,這樣寫和以前的寫法有什么的本質(zhì)的區(qū)別,這一點需要去研究一下。

基于類的面向?qū)ο蠛突谠偷拿嫦驅(qū)ο?/h3>
  • 基于類的面向?qū)ο?br> 在基于類的面向?qū)ο笳Z言中(比如Java和C++), 是構(gòu)建在類(class)和實例(instance)上的。其中類定義了所有用于具有某一特征對象的屬性。類是抽象的事物, 而不是其所描述的全部對象中的任何特定的個體。另一方面, 一個實例是一個類的實例化,是其中的一個成員。

  • 基于原型的面向?qū)ο?br> 在基于原型的語言中(如JavaScript)并不存在這種區(qū)別:它只有對象!不論是構(gòu)造函數(shù)(constructor),實例(instance),原型(prototype)本身都是對象?;谠偷恼Z言具有所謂的原型對象的概念,新對象可以從中獲得原始的屬性。

所以,在JavaScript中有一個很有意思的proto屬性(ES6以下是非標準屬性)用于訪問其原型對象, 你會發(fā)現(xiàn),上面提到的構(gòu)造函數(shù),實例,原型本身都有proto指向原型對象。其最后順著原型鏈都會指向Object這個構(gòu)造函數(shù),然而Object的原型對象的原型是null,不信, 你可以嘗試一下Object.prototype.proto === null為true。然而typeof null === 'object'為true。到這里, 我相信你應(yīng)該就能明白為什么JavaScript這類基于原型的語言中沒有類和實例的區(qū)別, 而是萬物皆對象!

封裝

js實現(xiàn)封裝的辦法和java其實差不多

function Person(name) {
  this.name = name
  var smallName = 'xiaoming'
}
Person. prototype.sayHi = function() {
  console.log('hello')
}

上面代碼,定義了一個私有變量smallName和一個方法sayHi,我們并不能通過實例化Person去訪問smallName,還有我們也不知道sayH是怎么實現(xiàn)的,這樣就實現(xiàn)了封裝。

繼承和多態(tài)

在es6以前,我最常使用的繼承方式是使用protutype

function Person(name) {
    this.name = name
    this.career = function() {
      console.log('I am a Person' + name)
    }
  }
  Person.prototype.sayHi = function () {
    console.log('my name is ' + this.name);
  }

  function Teacher(career) {
    this.career = function() {
      console.log('I am a ' + career + ', my name is ' + this.name)
    }
  }
  Teacher.prototype = new Person('Ma')
Teacher.prototype.constructor = Teacher

  var personOne  = new Person('Zhang')
  personOne.career()

  var teaMa = new Teacher('math')
  console.log(teaMa);
  teaMa.career()

Person是一個父類,子類Teacher想要繼承父類,就在它的prototype指向變?yōu)橐粋€新的父類實例,同時將prototype的constructor屬性指向自己,如果constructor屬性不指回自己的話,將會導(dǎo)致

console.log(teaMa.constructor === Person)  // true

這是一個重大錯誤,明明是Teacher實例化出來的,結(jié)果顯示父類實例化的......
新實例化的Teacher有父類的name屬性,這就實現(xiàn)了繼承,同時Person和Teacher類都有career方法,他們通過函數(shù)覆蓋實現(xiàn)了多態(tài)。

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

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

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