TypeScript全解:class(下)

成員可見(jiàn)性

  • public 類(lèi)外可見(jiàn)
  • private 類(lèi)內(nèi)可見(jiàn) #var 真私有屬性
  • protected 子類(lèi)和自己可見(jiàn)
// public 
class Person1 {
  public friend?: Person
  constructor(public name: string, friend?: Person) {
    this.friend = friend
  }
}
const p1 = new Person1('jack')
p1.friend // undefined

// private
class Person2 {
  private friend?: Person
  constructor(public name: string, friend?: Person) {
    this.friend = friend
  }
  xxx() {
    this. friend // TODO: 這里是可以使用的
  }
}
const p2 = new Person2('jack', p1)
p2.friend // TODO: typescript 報(bào)錯(cuò)

// protected
class Person3 {
  private friend?: Person
  constructor(public name: string, friend?: Person) {
    this.friend = friend
  }
  xxx() {
    this. friend // TODO: 這里是可以使用的
  }
}

class User extends Person3 {
  constructor(public id: number, name: string, friend?: User) {
    super(name, friend)
  }
  yyy() {
    this.friend  // TODO: 子類(lèi)這里是可以使用的
  }
}

const u = new User(1, 'jack')
u.friend // TODO: typescript 報(bào)錯(cuò)

但是這些代碼始終都會(huì)變成 JS
那么說(shuō),TS 提供的這三個(gè)關(guān)鍵詞還有用嘛?
顯然易見(jiàn):因?yàn)轭?lèi)型擦除,在 JS 中,你又可以隨心所欲了
但是我就想要私有屬性怎么辦,那就使用 JS 的 #

class Person {
  #friend?: Person
  constructor(public name: string, friend?: Person) {
    this.#friend = friend
  }
}

const p = new Person('jack')

p.friend // TODO: typescript 報(bào)錯(cuò)

static

static 的意思是這個(gè)屬性是通過(guò)類(lèi)名訪(fǎng)問(wèn)的

class Person {
  xxx = 1
  name: string
  constructor(name: string) {
    this.name = name
  }
}

Person.xxx // TODO: typescript 報(bào)錯(cuò)

所以為了解決上面的問(wèn)題,面向?qū)ο笥旨恿艘粋€(gè)關(guān)鍵字,static

class Person {
  static xxx = 1
  name: string
  constructor(name: string) {
    this.name = name
  }
}

Person.xxx // TODO: 可以使用了

這就叫做靜態(tài)屬性
這里在提示一下 name 叫做成員屬性
什么區(qū)別?靜態(tài)屬性是代碼執(zhí)行到哪一行的時(shí)候就初始化了,而成員屬性是實(shí)例化后才初始化的

但是使用 staic 的時(shí)候需要注意一點(diǎn)

他不能在固有屬性上使用

class Person {
  static name: string // TODO: 報(bào)錯(cuò)啦
  name: stirng
  constructor(name: string) {
    this.name = name
  }
}

為什么會(huì)這樣呢?
這又要追尋到 JS 的問(wèn)題了:JS 中的 class 是用函數(shù)實(shí)現(xiàn)的
怎么證明,用 typeof:


class 是個(gè) function,且自然自帶 name,這樣看來(lái),JS 中的 class 就是辣雞,看起來(lái)實(shí)現(xiàn)了 class,但又好像是個(gè)殘廢,所以有關(guān)固有屬性的都會(huì)報(bào)錯(cuò)

class Person {
  static length: string // TODO: 報(bào)錯(cuò)啦
  static prototype: string // TODO: 報(bào)錯(cuò)啦
  static arguments: string // TODO: 報(bào)錯(cuò)啦
  static caller: string // TODO: 報(bào)錯(cuò)啦
  name: stirng
  constructor(name: string) {
    this.name = name
  }
}

static block

需求是這樣:我們想記錄這個(gè)功能被創(chuàng)建過(guò)多少次?

如果是 JS 程序員,那么很簡(jiǎn)單

let count = parseInt(loocalStorage.getItem('count') || 0)

count += 1

如果是在 class 里面那就很難做到,除非~再加個(gè)語(yǔ)法

class Foo {
  static #count = 0
  static { // TODO: 注意這里,這種語(yǔ)法代表類(lèi)在創(chuàng)建的時(shí)候會(huì)執(zhí)行
    const count = loadFrimLocalStorage() || 0
    Foo.#count += count
  }
  constructor() {
    console.log(Foo.#count)
  }
}

類(lèi)和泛型

class Hash<K, V> {
  map: Map<K, V> = new Map()
  set(key: K, value: V) {
    this.map.set(key, value)
  }
  get(key: K) {
    return this.map.get(key)
  }
}

const h = new Hash<string | number, string | number>()
h.set('name', 'hi')
g.get('name')

其實(shí)上面這個(gè) Hash 就是一個(gè) Map,那么直接用繼承就好了

class Hash<K, V> extends Map<K, V> {
  destory() {
    this.clear()
  }
}

抽象類(lèi)

interface A {}
class B {}

interface 只能寫(xiě)類(lèi)型,不寫(xiě)實(shí)現(xiàn)
class 又寫(xiě)類(lèi)型,又寫(xiě)實(shí)現(xiàn)
人都喜歡折中
能不能有的實(shí)現(xiàn),有的不實(shí)現(xiàn)呢?
為了應(yīng)對(duì)這個(gè)需求,又來(lái)到了面向?qū)ο笫煜さ牟僮鳎?strong>加關(guān)鍵字, abstract

abstract class Person {
  a() {
    console.log('a')
  }
  abstract name: string
  abstract b: () => number
}

這就是抽象類(lèi),請(qǐng)注意這個(gè)抽象類(lèi)是不能直接使用的!

const p = new Person()
// TODO: 報(bào)錯(cuò):Cannot Create an Instance of an abstract class.ts

把類(lèi)當(dāng)作參數(shù)(常用)

把類(lèi)作為參數(shù),而不是把對(duì)象作為參數(shù)

class Person {}

function fn(X: Person) { // TODO: typescript 報(bào)錯(cuò)
  const p = new X()
}

fn(Person)

怎么解決呢?下面兩種方式

// 第一種:
function fn1(X: typeof Person) {
  const p = new X()
}

// 第二種:
function fn2(X: new (name: string) => Person) {
  const p = new X()
}

看起來(lái)很奇怪把~

個(gè)人對(duì) class 的看法

有這么多關(guān)鍵字,有這么多語(yǔ)法,搞的像背書(shū)一樣,每個(gè)關(guān)鍵字是什么意思,怎么組合,該怎么聲明類(lèi)型,全都是固定的,都是套路,都是模版,有什么好處呢?

那就是工業(yè)化,千人一面,大家寫(xiě)出來(lái)的代碼都是一樣的,即使你是新手,你也能看懂老手的代碼,大家溝通起來(lái)就簡(jiǎn)單多了。

如果說(shuō)面向?qū)ο筮m合前端就罷了,但是實(shí)際上來(lái)看,雖然以前轉(zhuǎn)向前端的都是面向隨想那幫人,他們自然而然在寫(xiě)前端時(shí)候會(huì)加入各種組合,各種設(shè)計(jì)模式,

但是從 ES6 開(kāi)始,前端就希望代碼更加簡(jiǎn)化,希望更多的函數(shù)和對(duì)象組合,雖然這個(gè)時(shí)候出了真正的關(guān)鍵詞 class,但是很多前端就是不用,你 class 的功能我全都可以用函數(shù)和對(duì)象來(lái)實(shí)現(xiàn),直到今年 react 和 vue 都出了 hooks API,他們連 this 都不用了,更不用說(shuō) new 了,所以事實(shí)證明,不用 class 也能寫(xiě)出很好的程序。

?著作權(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)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 一、JavaScript篇[https://www.w3school.com.cn/js/index.asp] J...
    不會(huì)敲代碼的小張閱讀 953評(píng)論 0 1
  • 前言 TypeScript(以后簡(jiǎn)稱(chēng)TS)是JavaScript(以后簡(jiǎn)稱(chēng)JS)的一個(gè)超級(jí),支持當(dāng)前最新的ES規(guī)范...
    FTD止水閱讀 656評(píng)論 0 0
  • 為什么要使用TS? 獲得更好的開(kāi)發(fā)體驗(yàn),解決JS中一些難以解決的問(wèn)題 JS存在的問(wèn)題: 使用了不存在的變量函數(shù)或者...
    小丹子1o1閱讀 782評(píng)論 0 0
  • TypeScript 是 JavaScript 的一個(gè)超集,主要提供了類(lèi)型系統(tǒng)和對(duì) ES6 的支持,它由 Micr...
    Gukson666閱讀 8,897評(píng)論 3 29
  • 基礎(chǔ)篇 1.ES為什么查詢(xún)效率快 傳統(tǒng)的數(shù)據(jù)庫(kù)采用的B+數(shù)索引,ES中為所有字段默認(rèn)都建了倒排索引 2.設(shè)計(jì)模式 ...
    磨陀貨_閱讀 1,156評(píng)論 0 2

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