Code Fix

上級

インスタンス全体で共有したい値をstaticにし忘れる

クラスのインスタンスをまたいで値を共有したい場合はstaticフィールドが必要です。staticを付け忘れると、その値はクラス自身ではなく各インスタンスに独立して属するため、期待した共有ができません。

なぜエラーが出ないのか

出力: NaN
(エラーなし)
JavaScriptは何も報告しません。文法として正しいためです
出力: NaN
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  class Widget {
 2           count = 0;
         ^
 3    constructor() {
 4      Widget.count++;
 5    }
 6  }
 7  new Widget();
 8  new Widget();
 9  new Widget();
10  console.log(Widget.count);
出力: NaN期待: 3 (エラーにはなりません)

staticを付けないcountはインスタンスごとのフィールドになり、Widget.countという静的プロパティは存在しません。undefined++の結果であるNaNがWidget.countに代入され続けます。

直し方: (空) を static にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  class Ticket {
 2           nextId = 1;
         ^
 3    constructor() {
 4      this.id = Ticket.nextId++;
 5    }
 6  }
 7  const t1 = new Ticket();
 8  const t2 = new Ticket();
 9  const t3 = new Ticket();
10  console.log(t3.id);
出力: NaN期待: 3 (エラーにはなりません)

nextIdをstaticにしないと、Ticket.nextIdはクラス自身のプロパティとして存在せず、undefined++でNaNになってしまいます。

直し方: (空) を static にします。

この問題を解いてみる →

パターン3

 1  class Logger {
 2           history = [];
         ^
 3    static log(msg) {
 4      Logger.history.push(msg);
 5    }
 6  }
 7  Logger.log("a");
 8  Logger.log("b");
 9  console.log(Logger.history.length);
main.js:4 Logger.history.push(msg); ^ TypeError: Cannot read properties of undefined (reading 'push')

historyをstaticにしないと、Logger.historyはクラス自身には存在せずundefinedのままです。pushを呼ぼうとした瞬間にエラーになります。

直し方: (空) を static にします。

この問題を解いてみる →

パターン4

 1  class Session {
 2           activeCount = 0;
         ^
 3    constructor() {
 4      Session.activeCount++;
 5    }
 6  }
 7  new Session();
 8  new Session();
 9  console.log(Session.activeCount);
出力: NaN期待: 2 (エラーにはなりません)

staticを付けないactiveCountはインスタンスごとのフィールドになり、Session.activeCountという静的プロパティは存在しません。

直し方: (空) を static にします。

この問題を解いてみる →

パターン5

 1  class Cache {
 2           store = {};
         ^
 3    static set(key, value) {
 4      Cache.store[key] = value;
 5    }
 6  }
 7  Cache.set("a", 1);
 8  console.log(Object.keys(Cache.store).length);
main.js:4 Cache.store[key] = value; ^ TypeError: Cannot set properties of undefined (setting 'a')

storeをstaticにしないと、Cache.storeはクラス自身には存在せずundefinedのままです。

直し方: (空) を static にします。

この問題を解いてみる →

よくある誤解

「クラスに書いたフィールドはクラス全体で1つのはず」という思い込みは誤りです。staticを付けない限り、フィールドはnewするたびに新しく作られる、インスタンスごとに独立した値になります。

実務での勘所

staticなメンバーは、そのクラスから作られる個々のインスタンスにではなく、クラスの関数オブジェクト自身に直接載ります(インスタンスメソッドがprototypeに載るのとは別の置き場所です)。典型的な使いどころは、「これまでに何個のインスタンスが作られたか」を数えるカウンタです。コンストラクタの中でMyClass.count++のように書けば、newを呼ぶたびにクラス自身が持つ1つの値が増えていき、どのインスタンスからアクセスしても同じ値を参照します。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)