JavaScriptでオブジェクトをインスタンス化するシンプルな方法

JavaScriptでオブジェクトをインスタンス化するシンプルな方法JS
この記事は約25分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●JavaScriptのクラスとインスタンスとは

プログラミング初心者の方にとって、クラスやインスタンスという言葉は少し難しく感じるかもしれません。

そこで、これからJavaScriptにおけるクラスとインスタンスの概念について、わかりやすく丁寧に解説していきますので、一緒に理解を深めていきましょう。

クラスとインスタンスは、オブジェクト指向プログラミングの重要な概念です。

オブジェクト指向は、現実世界の物事をプログラムに反映させる考え方で、コードの再利用性や保守性を高めることができます。

JavaScriptでもオブジェクト指向の機能が用意されており、クラスを定義してインスタンスを生成することが可能です。

クラスは、オブジェクトの設計図や雛形のようなものだと考えてください。例えば、「車」というクラスがあるとします。

車クラスには、車の特徴である「色」や「速度」などの情報(プロパティ)や、「加速する」「停止する」などの動作(メソッド)が定義されています。

一方、インスタンスは、クラスから生成される具体的な個々のオブジェクトを指します。

「赤い車」や「青い車」は、車クラスから生成されたインスタンスと言えます。

クラスは1つですが、そこから生成されるインスタンスは複数存在できます。

各インスタンスは、クラスで定義されたプロパティやメソッドを持ちながらも、それぞれ独立した存在として扱われます。

例えば、赤い車と青い車は同じ車クラスから生成されていても、色や速度の値は個別に設定や変更が可能です。

このように、クラスとインスタンスを使うことで、同じ種類のオブジェクトを効率的に扱うことができます。

コードの重複を減らし、構造化されたプログラムを書くことが可能になります。

これからサンプルコードを交えながら、JavaScriptでのクラスとインスタンスの使い方を具体的に見ていきましょう。

○クラスとインスタンスの違い

クラスとインスタンスの違いを理解することは、オブジェクト指向プログラミングを習得する上で非常に重要です。

クラスは、オブジェクトの設計図や雛形であり、オブジェクトがどのようなプロパティやメソッドを持つのかを定義します。

クラス自体は抽象的な概念であり、実際に使用されるのはクラスから生成されたインスタンスです。

一方、インスタンスは、クラスから生成される具体的な個々のオブジェクトです。

インスタンスは、クラスで定義されたプロパティやメソッドを持ち、それぞれが独立した存在として扱われます。

例えば、「人間」というクラスがあるとします。

人間クラスには、「名前」や「年齢」などのプロパティと、「歩く」や「話す」などのメソッドが定義されています。

そして、「太郎」や「花子」は、人間クラスから生成されたインスタンスです。

太郎と花子は、それぞれ固有の名前や年齢を持っていますが、どちらも人間クラスの特徴である歩くことや話すことができます。

つまり、クラスは設計図であり、インスタンスはその設計図に基づいて実際に生成されたオブジェクトということができます。

クラスは1つですが、そこから生成されるインスタンスは複数存在できるのです。

JavaScriptでは、クラスを定義するためにclassキーワードを使用します。次のサンプルコードで、クラスの定義方法を見ていきましょう。

○サンプルコード1:クラスの定義

JavaScriptでクラスを定義するには、classキーワードを使用します。

クラス名は通常、大文字で始めるのが慣例です。

クラス内には、コンストラクタ関数とメソッドを定義します。

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  sayHello() {
    console.log(`こんにちは、私の名前は${this.name}です。`);
  }
}

このコードでは、Personというクラスを定義しています。

constructorはコンストラクタ関数で、インスタンス生成時に呼び出されます。

コンストラクタ内で、thisキーワードを使ってインスタンスのプロパティ(nameage)を初期化しています。

sayHelloは、Personクラスのメソッドです。

このメソッドでは、インスタンスのnameプロパティを使って、挨拶文を出力しています。

クラスを定義することで、同じ構造を持つオブジェクトを簡単に作成できるようになります。

このクラスからインスタンスを生成する方法は、次のサンプルコードで説明します。

○サンプルコード2:インスタンスの生成

クラスからインスタンスを生成するには、newキーワードを使用します。

newの後にクラス名を指定し、必要な引数を渡すことでインスタンスが生成されます。

const taro = new Person("太郎", 25);
const hanako = new Person("花子", 20);

taro.sayHello(); // 出力結果:こんにちは、私の名前は太郎です。
hanako.sayHello(); // 出力結果:こんにちは、私の名前は花子です。

console.log(taro.age); // 出力結果:25
console.log(hanako.age); // 出力結果:20

このコードでは、Personクラスからtarohanakoの2つのインスタンスを生成しています。

new Person("太郎", 25)のように、コンストラクタに名前と年齢を引数として渡しています。

生成されたインスタンスは、それぞれ独立した存在として扱われます。

taro.sayHello()hanako.sayHello()を呼び出すと、それぞれのインスタンスの名前が挨拶文に反映されて出力されます。

また、インスタンスのプロパティにアクセスすることもできます。

taro.agehanako.ageを出力すると、それぞれのインスタンスの年齢が表示されます。

●newキーワードとコンストラクタの役割

JavaScriptでインスタンスを生成する際に重要な役割を果たすのが、newキーワードとコンストラクタです。

これらを理解することで、クラスからインスタンスを適切に生成し、初期化することができるようになります。

newキーワードは、クラスからインスタンスを生成するために使用します。

newの後にクラス名を指定すると、そのクラスのインスタンスが新しく作成されます。

この際、クラス内で定義されたコンストラクタが呼び出され、インスタンスの初期化処理が行われます。

コンストラクタは、クラス内でconstructorという名前で定義される特別なメソッドです。

インスタンス生成時に自動的に呼び出され、インスタンスのプロパティを初期化するための処理を記述します。

コンストラクタには、インスタンス生成時に渡された引数を受け取ることができ、それらの値を使ってプロパティを設定することが一般的です。

サンプルコードを見ながら、newキーワードとコンストラクタの使い方を詳しく見ていきましょう。

○サンプルコード3:コンストラクタの定義

コンストラクタは、クラス内でconstructorという名前で定義します。

コンストラクタには、インスタンス生成時に渡された引数を受け取るための引数リストを指定します。

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  getArea() {
    return this.width * this.height;
  }
}

このRectangleクラスでは、constructorが定義されています。

constructorは、widthheightの2つの引数を受け取ります。

thisキーワードを使って、インスタンスのプロパティwidthheightに、それぞれ引数の値を代入しています。

また、getAreaメソッドも定義されており、インスタンスのwidthheightを使って面積を計算して返します。

このようにコンストラクタを定義することで、インスタンス生成時に必要な初期化処理を行うことができます。

○サンプルコード4:newによるインスタンス化

newキーワードを使って、クラスからインスタンスを生成してみましょう。

const rectangle1 = new Rectangle(5, 3);
console.log(rectangle1.width); // 出力結果: 5
console.log(rectangle1.height); // 出力結果: 3
console.log(rectangle1.getArea()); // 出力結果: 15

const rectangle2 = new Rectangle(10, 7);
console.log(rectangle2.width); // 出力結果: 10
console.log(rectangle2.height); // 出力結果: 7
console.log(rectangle2.getArea()); // 出力結果: 70

new Rectangle(5, 3)のように、newキーワードの後にクラス名とコンストラクタの引数を指定することで、Rectangleクラスのインスタンスを生成しています。

生成されたインスタンスは、rectangle1変数に代入されます。

同様に、new Rectangle(10, 7)で別のインスタンスrectangle2を生成しています。

生成されたインスタンスのプロパティにアクセスすると、コンストラクタで初期化された値が取得できます。

rectangle1.width5rectangle1.height3となっています。

また、rectangle1.getArea()を呼び出すと、面積が計算されて15が返ってきます。

rectangle2についても同様に、プロパティの値やgetArea()の結果が期待通りになっていることが確認できます。

このように、newキーワードとコンストラクタを使うことで、クラスからインスタンスを生成し、それぞれのインスタンスごとに個別のデータを持つことができます。

○サンプルコード5:コンストラクタへの引数

コンストラクタには、インスタンス生成時に必要な引数を渡すことができます。

これにより、インスタンスごとに異なる初期値を設定することが可能になります。

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

  getArea() {
    return Math.PI * this.radius ** 2;
  }
}

const circle1 = new Circle(5);
console.log(circle1.radius); // 出力結果: 5
console.log(circle1.getArea()); // 出力結果: 78.53981633974483

const circle2 = new Circle(10);
console.log(circle2.radius); // 出力結果: 10
console.log(circle2.getArea()); // 出力結果: 314.1592653589793

このCircleクラスでは、コンストラクタがradius引数を受け取ります。

この引数の値は、インスタンスのradiusプロパティに代入されます。

new Circle(5)new Circle(10)で、それぞれ異なる半径のCircleインスタンスを生成しています。

生成されたインスタンスのradiusプロパティには、コンストラクタに渡された引数の値が設定されています。

また、getArea()メソッドを呼び出すと、インスタンスのradiusを使って円の面積が計算されます。

●インスタンス変数とメソッド

クラスからインスタンスを生成すると、各インスタンスは独自のデータを持つことができます。

このデータを保持するための変数をインスタンス変数と呼びます。

また、インスタンスが持つ関数のことをインスタンスメソッドと呼びます。

インスタンス変数とメソッドを使うことで、オブジェクト指向プログラミングの利点であるデータと操作の組み合わせを実現できます。

インスタンス変数は、constructor内でthisキーワードを使って定義します。

thisはインスタンス自身を参照するキーワードで、this.変数名のように使うことで、インスタンスに属する変数を定義できます。

こうして定義されたインスタンス変数は、インスタンスごとに異なる値を持つことができます。

一方、インスタンスメソッドは、クラス内で定義された関数です。

このメソッドは、インスタンスに対して呼び出すことができ、インスタンス変数を操作したり、インスタンスに関連する処理を行ったりします。

それでは、サンプルコードを見ながら、インスタンス変数とメソッドの使い方を詳しく見ていきましょう。

○サンプルコード6:インスタンス変数の定義と使用

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  introduce() {
    console.log(`私の名前は${this.name}で、${this.age}歳です。`);
  }
}

const person1 = new Person("太郎", 25);
const person2 = new Person("花子", 20);

person1.introduce(); // 出力結果: 私の名前は太郎で、25歳です。
person2.introduce(); // 出力結果: 私の名前は花子で、20歳です。

このPersonクラスでは、constructor内でthis.namethis.ageというインスタンス変数を定義しています。

これらの変数は、それぞれnameageの引数で初期化されます。

introduceメソッドは、インスタンス変数nameageを使って自己紹介のメッセージを出力します。

person1person2は、それぞれ異なるnameageの値で初期化されたPersonクラスのインスタンスです。

person1.introduce()person2.introduce()を呼び出すと、それぞれのインスタンスのnameageの値が使われて、自己紹介のメッセージが出力されます。

このように、インスタンス変数を使うことで、インスタンスごとに異なるデータを保持し、インスタンスメソッドからそのデータにアクセスすることができます。

○サンプルコード7:インスタンスメソッドの定義と呼び出し

インスタンスメソッドは、クラス内で定義された関数で、インスタンスに対して呼び出すことができます。

インスタンスメソッドは、インスタンス変数を操作したり、インスタンスに関連する処理を行ったりします。

class Calculator {
  constructor() {
    this.result = 0;
  }

  add(num) {
    this.result += num;
  }

  subtract(num) {
    this.result -= num;
  }

  getResult() {
    return this.result;
  }
}

const calc = new Calculator();

calc.add(10);
calc.subtract(3);
console.log(calc.getResult()); // 出力結果: 7

calc.add(5);
console.log(calc.getResult()); // 出力結果: 12

このCalculatorクラスでは、constructor内でthis.resultというインスタンス変数を定義し、初期値を0に設定しています。

addメソッドは、引数numを受け取り、this.resultに加算します。

subtractメソッドは、引数numを受け取り、this.resultから減算します。

getResultメソッドは、現在のthis.resultの値を返します。

calcは、Calculatorクラスのインスタンスです。

calc.add(10)calc.subtract(3)を呼び出すことで、calcインスタンスのresult変数が操作されます。

calc.getResult()を呼び出すと、現在のresultの値が取得できます。

その後、calc.add(5)を呼び出すと、resultの値が更新され、calc.getResult()を呼び出すと新しい値が取得できます。

このように、インスタンスメソッドを使うことで、インスタンス変数を操作し、インスタンスに関連する処理を行うことができます。

○サンプルコード8:thisキーワード

thisキーワードは、インスタンス自身を参照するために使用されます。

thisを使うことで、インスタンス変数やインスタンスメソッドにアクセスすることができます。

class Counter {
  constructor() {
    this.count = 0;
  }

  increment() {
    this.count++;
  }

  getCount() {
    return this.count;
  }

  reset() {
    this.count = 0;
  }
}

const counter = new Counter();

counter.increment();
counter.increment();
console.log(counter.getCount()); // 出力結果: 2

counter.reset();
console.log(counter.getCount()); // 出力結果: 0

このCounterクラスでは、constructor内でthis.countというインスタンス変数を定義し、初期値を0に設定しています。

incrementメソッドは、this.countの値を1増加させます。

getCountメソッドは、現在のthis.countの値を返します。resetメソッドは、this.countの値を0にリセットします。

counterは、Counterクラスのインスタンスです。

counter.increment()を2回呼び出すことで、counterインスタンスのcount変数が2増加します。

counter.getCount()を呼び出すと、現在のcountの値である2が取得できます。

counter.reset()を呼び出すと、countの値が0にリセットされ、counter.getCount()を呼び出すと0が取得できます。

●インスタンスの削除とメモリ管理

JavaScriptでインスタンスを扱う際、メモリ管理について理解することが重要です。

インスタンスが不要になった場合、適切に削除やメモリ解放を行わないと、メモリリークにつながる可能性があります。でも心配しないでください。

JavaScriptにはガベージコレクションという仕組みがあり、自動的にメモリを管理してくれます。

ガベージコレクションは、もう使用されなくなったオブジェクトを自動的に検出し、メモリから解放する仕組みです。

JavaScriptエンジンがこのガベージコレクションを行うため、開発者が明示的にメモリ解放を行う必要はありません。

ただし、ガベージコレクションの仕組みを理解しておくことで、メモリリークを防ぐことができます。

インスタンスのプロパティを削除する方法と、ガベージコレクションによるメモリ解放について、サンプルコードを見ながら詳しく説明していきますので、一緒に理解を深めていきましょう。

○サンプルコード9:インスタンスのプロパティ削除

インスタンスのプロパティを削除するには、delete演算子を使用します。

delete演算子は、オブジェクトのプロパティを削除し、メモリから解放します。

class Student {
  constructor(name, age, grade) {
    this.name = name;
    this.age = age;
    this.grade = grade;
  }
}

const student = new Student("太郎", 16, "高校1年生");

console.log(student.grade); // 出力結果: 高校1年生

delete student.grade;

console.log(student.grade); // 出力結果: undefined

このStudentクラスは、nameagegradeの3つのプロパティを持っています。

const student = new Student("太郎", 16, "高校1年生");で、Studentクラスのインスタンスstudentを生成しています。

最初のconsole.log(student.grade);では、studentインスタンスのgradeプロパティにアクセスし、"高校1年生"が出力されます。

delete student.grade;で、studentインスタンスのgradeプロパティを削除しています。

削除後のconsole.log(student.grade);では、gradeプロパティが存在しないため、undefinedが出力されます。

このように、delete演算子を使うことで、インスタンスのプロパティを削除し、メモリから解放することができます。

ただし、delete演算子はプロパティを削除するだけで、インスタンス自体は削除されません。

○サンプルコード10:参照の解放とガベージコレクション

JavaScriptでは、オブジェクトへの参照がなくなると、そのオブジェクトはガベージコレクションの対象になります。

ガベージコレクションは、定期的に不要になったオブジェクトを自動的に検出し、メモリから解放します。

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}

let point1 = new Point(1, 2);
let point2 = new Point(3, 4);

point1 = null;
point2 = null;

このPointクラスは、xyの2つのプロパティを持っています。

let point1 = new Point(1, 2);let point2 = new Point(3, 4);で、それぞれPointクラスのインスタンスpoint1point2を生成しています。

point1 = null;point2 = null;で、point1point2の参照をnullに設定しています。

これにより、Pointインスタンスへの参照がなくなります。

参照がなくなったインスタンスは、ガベージコレクションの対象となります。

JavaScriptエンジンが定期的にガベージコレクションを実行し、これらのインスタンスを自動的にメモリから解放します。

ただし、ガベージコレクションのタイミングはJavaScriptエンジンに依存するため、開発者が明示的に制御することはできません。

参照を適切に管理し、不要になったインスタンスへの参照を解放することで、メモリリークを防ぐことができます。

●JavaScriptのインスタンス化実践例

これまでJavaScriptのクラスとインスタンスについて学んできましたが、実際のアプリケーション開発ではどのように活用されているのでしょうか?

ここからは、具体的な実践例を見ながら、インスタンス化の使い方を深めていきましょう。

サンプルコードを通して、ユーザー情報の管理、複数インスタンスの扱い方、インスタンスの状態の変更と取得など、よくある場面でのインスタンス化の活用方法を解説していきます。

一緒に手を動かしながら、インスタンス化の実践的なスキルを身につけていきましょう。

○サンプルコード11:ユーザークラスの作成

ウェブアプリケーションでは、ユーザー情報を管理するためにクラスを使うことがよくあります。

ここでは、Userクラスを作成し、ユーザーのプロパティとメソッドを定義してみましょう。

class User {
  constructor(id, name, email) {
    this.id = id;
    this.name = name;
    this.email = email;
  }

  getId() {
    return this.id;
  }

  getName() {
    return this.name;
  }

  getEmail() {
    return this.email;
  }

  setName(name) {
    this.name = name;
  }

  setEmail(email) {
    this.email = email;
  }
}

const user = new User(1, "太郎", "taro@example.com");
console.log(user.getId()); // 出力結果: 1
console.log(user.getName()); // 出力結果: 太郎
console.log(user.getEmail()); // 出力結果: taro@example.com

user.setName("花子");
user.setEmail("hanako@example.com");
console.log(user.getName()); // 出力結果: 花子
console.log(user.getEmail()); // 出力結果: hanako@example.com

このUserクラスは、idnameemailの3つのプロパティを持ち、それぞれのゲッターとセッターメソッドが定義されています。

const user = new User(1, "太郎", "taro@example.com");で、Userクラスのインスタンスuserを生成し、初期値を設定しています。

user.getId()user.getName()user.getEmail()を呼び出すことで、それぞれのプロパティの値を取得できます。

user.setName("花子")user.setEmail("hanako@example.com")で、userインスタンスのnameemailプロパティの値を変更しています。

変更後のuser.getName()user.getEmail()を呼び出すと、新しい値が取得できることが確認できます。

このように、クラスを使ってユーザー情報を管理することで、データの構造化とカプセル化が実現できます。

○サンプルコード12:複数インスタンスの管理

アプリケーションでは、複数のユーザーを扱うことが一般的です。

ここでは、Userクラスを使って、複数のユーザーインスタンスを管理する方法を見てみましょう。

const users = [];

users.push(new User(1, "太郎", "taro@example.com"));
users.push(new User(2, "花子", "hanako@example.com"));
users.push(new User(3, "次郎", "jiro@example.com"));

for (const user of users) {
  console.log(`ID: ${user.getId()}, 名前: ${user.getName()}, メールアドレス: ${user.getEmail()}`);
}
// 出力結果:
// ID: 1, 名前: 太郎, メールアドレス: taro@example.com
// ID: 2, 名前: 花子, メールアドレス: hanako@example.com
// ID: 3, 名前: 次郎, メールアドレス: jiro@example.com

usersは、Userインスタンスを格納する配列です。

users.push()を使って、Userインスタンスを配列に追加しています。

それぞれのインスタンスは、異なるIDと初期値を持っています。

for...ofループを使って、users配列内の各Userインスタンスに対して処理を行っています。

ループ内では、各インスタンスのゲッターメソッドを呼び出して、プロパティの値を出力しています。

出力結果から、それぞれのUserインスタンスが個別のデータを持っていることがわかります。

このように、配列を使って複数のインスタンスを管理することで、データの一括処理や検索が容易になります。

○サンプルコード13:インスタンスの状態の変更と取得

インスタンスは、独自の状態を持ち、その状態を変更したり取得したりすることができます。

ここでは、Userクラスに新しいプロパティとメソッドを追加して、インスタンスの状態の変更と取得を行ってみましょう。

class User {
  constructor(id, name, email) {
    this.id = id;
    this.name = name;
    this.email = email;
    this.isActive = true;
  }

  // ... 他のメソッドは省略 ...

  activate() {
    this.isActive = true;
  }

  deactivate() {
    this.isActive = false;
  }

  isUserActive() {
    return this.isActive;
  }
}

const user = new User(1, "太郎", "taro@example.com");
console.log(user.isUserActive()); // 出力結果: true

user.deactivate();
console.log(user.isUserActive()); // 出力結果: false

user.activate();
console.log(user.isUserActive()); // 出力結果: true

Userクラスに、isActiveプロパティを追加しています。

このプロパティは、ユーザーがアクティブかどうかを表すブール値です。初期値はtrueに設定されています。

activate()メソッドは、isActivetrueに設定し、ユーザーをアクティブ状態にします。

deactivate()メソッドは、isActivefalseに設定し、ユーザーを非アクティブ状態にします。

isUserActive()メソッドは、現在のisActiveの値を返します。

userインスタンスを生成した直後は、isActivetrueなので、user.isUserActive()trueを返します。

user.deactivate()を呼び出すと、isActivefalseに変更され、user.isUserActive()falseを返します。

user.activate()を呼び出すと、再びisActivetrueに変更され、user.isUserActive()trueを返します。

このように、インスタンスの状態を変更し、取得することで、オブジェクトの振る舞いを柔軟に制御できます。

まとめ

JavaScriptにおけるクラスとインスタンスについて、その概念から実践的な使い方まで解説してきました。

クラスは設計図であり、インスタンスはその設計図から生成される実体です。

newキーワードとコンストラクタを使ってインスタンスを生成し、インスタンス変数やメソッドを通してデータと操作を組み合わせることで、柔軟で効率的なプログラミングが可能になります。

それでは、本記事で解説した知識を活かして、より効率的で保守性の高いコードを書いていきましょう。