クラスとインスタンス
このレッスンで分かること
classとconstructorで、同じ形のオブジェクトを何個でも作れます- メソッドの中の
thisは、呼び出したインスタンスを指します
データ専用の関数が、データから離れていく
入門では、プロフィールのスキルを素のオブジェクトの配列で持っていました。
JavaScript
const skills = [
{ name: "HTML", hours: 12 },
{ name: "CSS", hours: 8 }
];
function caption(skill) {
return skill.name + " " + skill.hours + " 時間";
}
function needsPractice(skill) {
return skill.hours < 10;
}caption も needsPractice も、スキルにしか使えない関数です。それなのにスキルのデータとは別の場所に置かれています。あとで hours を minutes に変えると、離れた場所にある関数を全部探して直すことになります。データと、そのデータ専用の処理が離れているのが原因です。
設計図を書いて、実体を作る
class を使うと、その 2 つを同じ波かっこの中に置けます。
JavaScript
class Skill {
constructor(name, hours) {
this.name = name;
this.hours = hours;
}
caption() {
return `${this.name} ${this.hours} 時間`;
}
needsPractice() {
return this.hours < 10;
}
}
const first = new Skill("HTML", 12);
console.log(first.caption()); // HTML 12 時間
console.log(first.needsPractice()); // falsenew Skill("HTML", 12) を書いたとき、JavaScript は次の順に動きます。
| 順番 | 起きること |
|---|---|
| 1 | 中身が空のオブジェクトが 1 個作られる |
| 2 | そのオブジェクトを this として constructor が呼ばれる |
| 3 | this.name = name などでプロパティが書き込まれる |
| 4 | できあがったオブジェクトが new 式の値として返る |
constructor の中では return を書きません。書かなくても、作られたオブジェクトが返ります。new を書き忘れて Skill("HTML", 12) と呼ぶと TypeError になります。クラスは new なしでは呼べない決まりなので、間違いに気付きやすい形です。
メソッドは、インスタンスを 100 個作っても 100 個には増えません。実体は 1 つで、全インスタンスがそれを見に行きます。this は「どのインスタンスから呼ばれたか」で決まるので、a.caption() なら this は a、b.caption() なら this は b です。
配列をまるごとインスタンスに変える
外から届くデータは素のオブジェクトです。第2章で使った map を通せば、配列ごと変えられます。
JavaScript
const records = [
{ name: "HTML", hours: 12 },
{ name: "CSS", hours: 8 }
];
const list = records.map((record) => new Skill(record.name, record.hours));
console.log(list.map((skill) => skill.caption()));
console.log(list.filter((skill) => skill.needsPractice()).length); // 1一度インスタンスにしてしまえば、そのあとは map も filter もこれまでどおりです。違うのは、配列の中身が処理のしかたを自分で知っている点です。
クラスは「オブジェクトの新しい書きかた」ではありません。同じ形のものが何個も出てきて、そのすべてに同じ処理をしたいときに効きます。1 個しか作らないなら、素のオブジェクトのままで十分です。
よくある間違い
- メソッドの間にカンマを書く — オブジェクトリテラルの感覚でカンマを打つと構文エラーです。クラスの本体はカンマで区切りません
- メソッドの中で
thisを書き忘れる —${name}とだけ書くと、インスタンスのプロパティではなく変数を探しに行き、見つからなければReferenceErrorです constructorで値を返そうとする — オブジェクトをreturnするとnewの結果がそれに差し替わり、メソッドを持たない素のオブジェクトができます。thisに代入するだけにします
要件
- class Work を定義する。constructor は title year views の 3 つを受け取り、同じ名前のプロパティに入れる
- Work に label() を持たせる。
タイトル (年)の形の文字列を返す。年の前後に半角スペースは入れない - Work に isPopular() を持たせる。views が 100 以上のとき true を返す
- function buildWorkSummary(items) を定義する。items は { title, year, views } の配列。すべて Work のインスタンスに変えたうえで { labels, popularCount } を返す
入出力例
buildWorkSummary([{"title":"プロフィールサイト","views":120,"year":2026},{"title":"自己紹介カード","views":48,"year":2026},{"title":"スキル一覧の表","views":32,"year":2026}]) → {"labels":["プロフィールサイト (2026)","自己紹介カード (2026)","スキル一覧の表 (2026)"],"popularCount":1}
buildWorkSummary([]) → {"labels":[],"popularCount":0}
buildWorkSummary([{"title":"作品ギャラリー","views":100,"year":2026}]) → {"labels":["作品ギャラリー (2026)"],"popularCount":1}
buildWorkSummary([{"title":"学習ログ","views":99,"year":2025}]) → {"labels":["学習ログ (2025)"],"popularCount":0}