前言

今天刷題刷到 988. Smallest String Starting From Leaf,要在二元樹中計算字典順序最小的字串, 其中一個操作是要將 node.val 轉換成字串才能進行字典大小比較,所以用到 String.fromCharCode() 來進行轉換, 也順便想起 ''.charCodeAt() 可以將字串轉換成 Unicode 碼位,因為這兩個方法常常配合使用, 也因為之後要準備面試,也嘗試著自己解釋下兩者的差異,發現沒有辦法一次就解釋得很清楚, 所以做了些筆記紀錄下兩者的差異和使用時機加深印象。

靜態方法(Static)跟原型方法(Prototype)的差別

靜態方法和原型方法在使用方式和作用域上有所不同,

  1. 靜態方法(Static Methods):
    • 靜態方法屬於類(class)本身,而不是類的實例(Instance),因此在使用時不需要創建類的實例。
    • 可以通過類本身直接調用,例如 String.fromCharCode(65)。 'A'
    • 靜態方法通常用於提供與類相關的工具函數或工廠函數,而不是操作實例本身。
  2. 原型方法(Prototype Methods):
    • 原型方法屬於類的原型(Prototype),可以在類的每個實例上調用。
    • 原型方法通常用於定義對實例操作的方法,例如 "".charCodeAt(0) 是針對字符串實例的方法。

要設計一個 class 時,該如何判斷要將功能做成 Static methods 還是 Prototype methods

可以由下面幾點因素來思考

  1. 是否需要訪問實例的狀態:原型方法可以訪問 this 關鍵字來引用當前實例。

  2. 是否與類的實例直接相關:靜態方法可以直接由類調用,而不需要實例。

  3. 是否需要在實例化之前就可以使用:這樣可以避免不必要的實例化。

  4. 是否需要在子類中覆蓋:

  5. 以 String.fromCodeAt 和 ''.charCodeAt() 為例

    • String.fromCharCode 的使用與特定字串實例無關,可以直接由 String 類調用,並根據傳入的 Unicode 碼點返回對應的字符。 傳入值也不指定要特定字串(允許數字或字串)。所以設計成 Static methods。
    • ''.charCodeAt() 的使用與特定字串實例相關,是用來獲取特定字串的 Unicode 碼點。使用錢要先訪問實例內部的字符,因此設計成原型方法。

嘗試設計一個信用卡 Class Card {}

假設要設計一個信用卡 Class Card ,以下方法哪些適合設計成 Static methods, 哪些設計成 Prototype methods

適合設計成 Static methods (與信用卡實例的狀態無關者)
  1. validateCardNumber(cardNumber): 驗證信用卡號是否有效。
  2. generateCardNumber(cardType): 生成指定類型的信用卡號。
  3. getCardType(cardNumber): 根據信用卡號獲取信用卡類型。
適合設計成 Prototype methods (須先進行實例才能進行操作者)
  1. charge(amount): 用信用卡支付特定金額。
  2. getBalance(): 獲取信用卡當前餘額。
  3. makePayment(amount): 用戶對信用卡進行還款。
class Card {
  constructor(location, balance) {
    this.location = location;
    this.balance = balance;
  }
  static validateCardNumber(cardNumber) {
    return cardNumber.length == 16;
  }
  getBalance() {
    return this.balance;
  }
}

class JCB extends Card {
  constructor(location, balance, branch, cardNumber) {
    super(location, balance); // 調用父類的 constructor,將父類需要的參數傳遞過去。
    this.branch = branch;
    this.cardNumber = cardNumber;
  }
}

let My_JCB_Card = new JCB("Taiwan", 1600, "taipei area", "1111222233334444");
console.log(My_JCB_Card.location); // 'Taiwan'
console.log(My_JCB_Card.branch); // 'taipei area'
console.log(Card.validateCardNumber(My_JCB_Card.cardNumber)); // true
console.log(My_JCB_Card.getBalance()); // 1600