インスタンス全体で共有したい値を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);
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);
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);
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);
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);
storeをstaticにしないと、Cache.storeはクラス自身には存在せずundefinedのままです。
直し方: (空) を static にします。
よくある誤解
「クラスに書いたフィールドはクラス全体で1つのはず」という思い込みは誤りです。staticを付けない限り、フィールドはnewするたびに新しく作られる、インスタンスごとに独立した値になります。
実務での勘所
staticなメンバーは、そのクラスから作られる個々のインスタンスにではなく、クラスの関数オブジェクト自身に直接載ります(インスタンスメソッドがprototypeに載るのとは別の置き場所です)。典型的な使いどころは、「これまでに何個のインスタンスが作られたか」を数えるカウンタです。コンストラクタの中でMyClass.count++のように書けば、newを呼ぶたびにクラス自身が持つ1つの値が増えていき、どのインスタンスからアクセスしても同じ値を参照します。