iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0

什麼叫靜態方法

靜態方法是一種直接附加在class上的方法,使用class建立的instance無法存取,也就是,它不在instance的[[protorype]]裡。
所以這個方法的使用與instance的狀態無關,也就是說,它不會取用instance裡的屬性,不依靠instance的東西作動態計算
像下面就是方法與instance的狀態有關,而static method就是跟這種狀況相反。

class Circle {
  constructor(radius) {
    this.radius = radius;
  }

  get area() {
    return Math.PI * this.radius * this.radius; 
  }
}

const circle1 = new Circle(5);
console.log(circle1.area); //看instance的半徑設多少,進而算出面積,與instamce狀態有關

為什麼要有靜態方法

什麼樣的情境下,我們會需要與instance無關的方法,其實我剛開始很難想像,不過下面的例子給了很好的解釋。
一樣使用前幾篇文都有用到的Person的例子,我們先用Person class建立兩個instance,並計算出他們的年紀,最後我們希望能比較他們的年紀看誰較為年長這樣。
在PersonCl裡寫入一個靜態方法compareAge,因為要比較兩個人的年紀,所以這個函數必須跟兩個instance有關,以一般物件取用方法是無法同時能關連兩個instances的內容,所以改用將兩人的年紀作為引數,然後把方法綁定在class上,這就是為什麼需要有靜態方法的原因。
下面的code有稍微再改寫過,原本是引入兩人年紀到compareAge,改為引入兩個物件整體,如此一來能再印出訊息時,進一步帶入兩人的名字。

class PersonCl {
  constructor(firstName, birthYear) {
    this.firstName = firstName;
    this.birthYear = birthYear;
  }
  calcAge() {
    return 2023 - this.birthYear;
  }

  static compareAge(person1, person2) {
    const age1 = person1.calcAge();
    const age2 = person2.calcAge();

    if (age1 === age2) {
      console.log(
        `${person1.firstName} and ${person2.firstName} are at the same age`
      );
    } else if (age1 > age2) {
      console.log(`${person1.firstName} is older than ${person2.firstName}`);
    } else {
      console.log(`${person1.firstName} is younger than ${person2.firstName}`);
    }
  }
}

const john = new PersonCl("John", 1990);
const sarah = new PersonCl("Sarah", 1995);
PersonCl.compareAge(john, sarah);

靜態方法的應用情境

由上面的例子可以看出,

  • 靜態方法的使用情境大多是把instance看成一個東西,然後對它做處理,而非與instance的內部狀態有關。
    比如說要比較兩個instances,要在某個特定的instance加東西,像是Object.create()作的事。
    下面舉了一個與Object.create()很類似的例子,都是利用靜態方法對一個特定instance加東西。比如說我想利用Person創建一個我還不知道它的詳細資訊的人物物件,我可以先寫一個靜態方法,能把預設的人物訊息寫入instance。
class PersonCl {
  constructor(firstName, birthYear) {
    this.firstName = firstName;
    this.birthYear = birthYear;
  }
  calcAge() {
    return 2023 - this.birthYear;
  }

  static defaultImfo() {
    return new this("default_name", 1990);
  }
}
const defaultPerson = PersonCl.defaultImfo();
console.log(defaultPerson);

執行結果:

必較一下之前Object.create()的例子

const PersonProto = {
  calcAge: function calcAge() {
    return 2023 - this.birthYear;
  },
};
const john = Object.create(PersonProto);

const defaultPerson = PersonCl.defaultImfo();>>將預設值放進instance
const john = Object.create(PersonProto);>>把某個函式放進instance的[[prototype]]
這兩行都是利用class呼叫靜態方法來對特定instance作了一些事。

  • 或者根本跟instance無關,像是Math這個build-in object裡就包含了許多靜態方法和靜態屬性能取用,像是能產生一的隨機亂數的ramdom()
console.log(Math.random()); 

下面舉了一個與instance無關,自定static method的例子(不過這是為舉例而舉例,好像實際上不會這樣用..)

class PersonCl {
  constructor(firstName, birthYear) {
    this.firstName = firstName;
    this.birthYear = birthYear;
  }
  calcAge() {
    return 2023 - this.birthYear;
  }
  static helloWorld() {
    console.log("Hello World!!😀");
  }
}
PersonCl.helloWorld(); //Hello World!!😀

今日總結

靜態方法指的是直接附加在class上的方法,instance無法取用,主要的使用場景為與instance完全無關,或者把instance看成一個東西,對這個東西作了些處理這樣。
咦?怎麼感覺總結得不是太好...(再次遮臉)

Reference

Static Methods In JavaScript
JavaScript static keyword
MDN-Math


上一篇
js的OOP:ES 6 class & Object.create()
下一篇
各式各樣的prototype chain (上)
系列文
超低腦容量學習法遇到javascript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言