第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

TypeScript 類(Class)

自 ES6 起,終于迎來了 class,對于開發(fā)者來說,終于可以使用基于類的面向?qū)ο笫骄幊?。TypeScript 在原 ES6 中類的基礎(chǔ)上,還添加了一些新的功能,比如幾種訪問修飾符,這是在其他面向?qū)ο笳Z言中早就實現(xiàn)了的。

JavaScript 的類作為語法糖,我們不但需要知道怎么去使用,還應(yīng)該了解其本質(zhì),涉及到原型的部分希望大家能深入理解。

1. 慕課解釋

類描述了所創(chuàng)建的對象共同的屬性和方法。通過 class 關(guān)鍵字聲明一個類,主要包含以下模塊:

  • 屬性
  • 構(gòu)造函數(shù)
  • 方法

2. 類的本質(zhì)

JavaScript 中,生成實例對象可以通過構(gòu)造函數(shù)的方式:

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
function Calculate (x, y) {
  this.x = x
  this.y = y
}

Calculate.prototype.add = function () {
  return this.x + this.y
}

var calculate = new Calculate(1, 2)
console.log(calculate.add()) // 3
運(yùn)行案例 點擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

如果通過 class 關(guān)鍵字進(jìn)行改寫:

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
class Calculate {
  // 類的屬性
  public x: number
  public y: number

  // 構(gòu)造函數(shù)
  constructor(x: number, y: number) {
    this.x = x
    this.y = y
  }

  // 類的方法
  add () {
    return this.x + this.y
  }
}

const calculate = new Calculate(1, 2)
console.log(calculate.add()) // 3

console.log(typeof Calculate) // 'function'
console.log(Calculate === Calculate.prototype.constructor) // true
運(yùn)行案例 點擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

代碼解釋:

最后一行,可以看出,類指向其構(gòu)造函數(shù)本身,class 關(guān)鍵字可以看做是一個語法糖。

constructor() 方法是類的默認(rèn)方法,通過 new 來生成對象實例時,自動調(diào)用該方法。換句話說,constructor() 方法默認(rèn)返回實例對象 this

3. 類的繼承

基于類的程序設(shè)計中一種最基本的模式是允許使用繼承來擴(kuò)展現(xiàn)有的類,這樣可以抽出公共部分讓子類復(fù)用。

使用 extends 關(guān)鍵字來實現(xiàn)繼承:

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
// 繼承 JavaScript 內(nèi)置的 Date 對象
class LinDate extends Date {

  getFormattedDate() {
    var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
    return this.getDate() + "-" + months[this.getMonth()] + "-" + this.getFullYear();
  }
}

const date = new LinDate()

console.log(date.getFullYear());     // 2020
console.log(date.getFormattedDate()) // 7-Jan-2020
運(yùn)行案例 點擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

代碼解釋: LinDate 繼承了 Date 的功能,可以使用父類 Date 的方法 getFullYear(),也可以使用自身的方法 getFormattedDate()。

子類在 constructor 內(nèi)中使用 super() 方法調(diào)用父類的構(gòu)造函數(shù),在一般方法內(nèi)使用 super.method() 執(zhí)行父類的方法。

實例演示
預(yù)覽 復(fù)制
復(fù)制成功!
class Animal {
  public name:string

  constructor(name: string) { 
    this.name = name 
  }

  move(distance: number = 0) {
      console.log(`${this.name} moved ${distance}m.`)
  }
}

class Dog extends Animal {
  constructor(name: string) { 
    // 調(diào)用父類的構(gòu)造函數(shù)
    super(name)
  }

  move(distance = 10) {
      console.log('bark...')
      // 執(zhí)行父類的方法
      super.move(distance) 
  }
}

const dog: Animal = new Dog('Coco')

dog.move() // Coco moved 10m.
運(yùn)行案例 點擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

代碼解釋:

第 16 行,通過 super() 調(diào)用了父類的構(gòu)造函數(shù)。

第 22 行,通過 super 關(guān)鍵字調(diào)用父類的方法。

4. 訪問修飾符

TypeScript 可以使用四種訪問修飾符 public、protected、private 和 readonly。

4.1 public

TypeScript 中,類的成員全部默認(rèn)為 public,當(dāng)然你也可以顯式的將一個成員標(biāo)記為 public,標(biāo)記為 public 后,在程序類的外部可以訪問。

class Calculate {
  // 類的屬性
  public x: number
  public y: number

  // 構(gòu)造函數(shù)
  public constructor(x: number, y: number) {
    this.x = x
    this.y = y
  }

  public add () {
    return this.x + this.y
  }
}

4.2 protected

當(dāng)成員被定義為 protected 后,只能被類的內(nèi)部以及類的子類訪問。

class Base {
  protected baseUrl: string = 'http://api.com/'

  constructor() {}

  protected request(method: string) {
    const url = `${this.baseUrl}${method}`
    // TODO 封裝基礎(chǔ)的 http 請求
  }
}

class Address extends Base {
  get() {
    return this.request('address')
  }
}

代碼解釋:

第 2 行,Base 類的屬性 baseUrl 被定義為受保護(hù)的,那么第 7 行該屬性在類中被訪問是可以的。

第 14 行,因 Address 類是 Base 類的子類,在子類中允許訪問父類中被定義為受保護(hù)類型的方法 request() 。

4.3 private

當(dāng)類的成員被定義為 private 后,只能被類的內(nèi)部訪問。

class Mom {
  private labour() {
    return 'baby is coming'
  }
}

class Son extends Mom {
  test () {
    this.labour() // Error, Property 'labour' is private and only accessible within class 'Mom'
  }
}

代碼解釋:

第 9 行,父類中的 labour() 方法被定義為私有方法,只能在父類中被使用,子類中調(diào)用報錯。

4.4 readonly

通過 readonly 關(guān)鍵字將屬性設(shè)置為只讀的。只讀屬性必須在聲明時或構(gòu)造函數(shù)里被初始化。

class Token {
  readonly secret: string = 'xjx*xh3GzW#3'

  readonly expired: number

  constructor (expired: number) {
    this.expired = expired
  } 
}

const token = new Token(60 * 60 * 24)
token.expired = 60 * 60 * 2 // Error, expired 是只讀的

代碼解釋:

最后一行,因 Token 類的屬性 expired 被設(shè)置為只讀屬性,不可被修改。

5. 靜態(tài)方法

通過 static 關(guān)鍵字來創(chuàng)建類的靜態(tài)成員,這些屬性存在于類本身上面而不是類的實例上。

class User {
  static getInformation () {
    return 'This guy is too lazy to write anything.'
  }
}

User.getInformation() // OK

const user = new User()
user.getInformation() // Error 實例中無此方法

代碼解釋: getInformation() 方法被定義為靜態(tài)方法,只存在于類本身上,類的實例無法訪問。

靜態(tài)方法調(diào)用同一個類中的其他靜態(tài)方法,可使用 this 關(guān)鍵字。

class StaticMethodCall {

  static staticMethod() {
      return 'Static method has been called'
  }
  static anotherStaticMethod() {
      return this.staticMethod() + ' from another static method'
  }

}

代碼解釋: 靜態(tài)方法中的 this 指向類本身,而靜態(tài)方法也存在于類本身,所以可以在靜態(tài)方法中用 this 訪問在同一類中的其他靜態(tài)方法。

非靜態(tài)方法中,不能直接使用 this 關(guān)鍵字來訪問靜態(tài)方法。而要用類本身或者構(gòu)造函數(shù)的屬性來調(diào)用該方法:

class StaticMethodCall {
  constructor() {
      // 類本身調(diào)用
      console.log(StaticMethodCall.staticMethod())

      // 構(gòu)造函數(shù)的屬性調(diào)用
      console.log(this.constructor.staticMethod())
  }
  static staticMethod() {
      return 'static method has been called.'
  }
}

代碼解釋: 類指向其構(gòu)造函數(shù)本身,在非靜態(tài)方法中,this.constructor === StaticMethodCalltrue, 也就是說這兩種寫法等價。

6. 抽象類

抽象類作為其它派生類的基類使用,它們一般不會直接被實例化,不同于接口,抽象類可以包含成員的實現(xiàn)細(xì)節(jié)。

abstract 關(guān)鍵字是用于定義抽象類和在抽象類內(nèi)部定義抽象方法。

abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log('roaming the earch...');
    }
}

const animal = new Animal() // Error, 無法創(chuàng)建抽象類實例

通常我們需要創(chuàng)建子類繼承抽象類,將抽象類中的抽象方法一一實現(xiàn),這樣在大型項目中可以很好的約束子類的實現(xiàn)。

class Dog extends Animal {
  makeSound() {
    console.log('bark bark bark...')
  }
}

const dog = new Dog()

dog.makeSound()  // bark bark bark...
dog.move()       // roaming the earch...

7. 把類當(dāng)做接口使用

類也可以作為接口來使用,這在項目中是很常見的。

class Pizza {
  constructor(public name: string, public toppings: string[]) {}
}

class PizzaMaker {
  // 把 Pizza 類當(dāng)做接口
  static create(event: Pizza) {
    return new Pizza(event.name, event.toppings)
  }
}

const pizza = PizzaMaker.create({ 
  name: 'Cheese and nut pizza', 
  toppings: ['pasta', 'eggs', 'milk', 'cheese']
})

第 7 行,把 Pizza 類當(dāng)做接口。

因為接口和類都定義了對象的結(jié)構(gòu),在某些情況下可以互換使用。如果你需要創(chuàng)建一個可以自定義參數(shù)的實例,同時也可以進(jìn)行類型檢查,把類當(dāng)做接口使用不失為一個很好的方法。

這就是 TypeScript 的強(qiáng)大功能,而且非常靈活,擁有全面的面向?qū)ο笤O(shè)計和通用的類型檢查。

8. 小結(jié)

本節(jié)介紹了類的本質(zhì)及其使用方法,需要注意:

  • 類指向其構(gòu)造函數(shù)本身。
  • 靜態(tài)方法存在于類本身上面而不是類的實例上。
  • 抽象類中的抽象方法不包含具體實現(xiàn)并且必須在派生類中實現(xiàn)。
  • TypeScript 新增了 public、protected、private 等訪問修飾符。
  • 子類繼承父類時,在其構(gòu)造函數(shù) constructor() 中不要忘了 super() 方法。