【JavaScript】new演算子を使用して新しいオブジェクトを生成する方法

new 演算子は、コンストラクタ関数や class から新しいオブジェクト(インスタンス)を生成するための演算子です。オブジェクト指向プログラミングの基本になります。

この記事では、new が内部で何をしているかを押さえたうえで、現代的な class 構文や、メソッドを共有する仕組み、よくある落とし穴まで解説します。

この記事の結論:new コンストラクタ() で新しいオブジェクトを生成します。内部では「空オブジェクト生成 → prototypeリンク → this束縛 → 返却」が行われます。現代のJavaScriptではclass 構文が標準で、new を忘れても TypeError で気づける安全さがあります。
スポンサーリンク

newの基本(コンストラクタ関数)

まずは古くからあるコンストラクタ関数の例です。関数を「オブジェクトのひな型」として使い、new を付けて呼び出します。

JavaScript:コンストラクタ関数とnew
function Person(name, age) {
  this.name = name;
  this.age = age;
}

const person1 = new Person("Alice", 25);
console.log(person1.name); // "Alice"
console.log(person1.age);  // 25

newが内部でやっていること(4ステップ)

new Person("Alice", 25) を実行すると、次の順で処理されます。

  1. 新しい空のオブジェクトが作られる
  2. そのオブジェクトの内部プロトタイプが、コンストラクタの prototype を指すようになる
  3. コンストラクタが this を新しいオブジェクトに束縛して実行される
  4. コンストラクタが別のオブジェクトを明示的に返さない限り、新しいオブジェクトが返される

2番目のプロトタイプのつながりは、Object.getPrototypeOf() で確認できます(非推奨の __proto__ ではなくこちらを使います)。

JavaScript:プロトタイプのつながりを確認
const p = new Person("Bob", 30);
console.log(Object.getPrototypeOf(p) === Person.prototype); // true

メソッドはprototypeで共有する

全インスタンスで共通の処理は、prototype にメソッドを定義します。するとそのメソッドは全インスタンスで共有され、メモリ効率が良くなります。

JavaScript:prototypeメソッド
function Person(name) {
  this.name = name;
}
Person.prototype.greet = function () {
  return `こんにちは、${this.name}です`;
};

const a = new Person("Alice");
const b = new Person("Bob");
console.log(a.greet()); // "こんにちは、Aliceです"

// メソッドの実体は1つだけ(全インスタンスで共有)
console.log(a.greet === b.greet); // true

現代的な書き方:class

ES2015以降は class 構文が標準です。constructor で初期化し、メソッドをそのまま書けば prototype に定義されます。見た目が分かりやすく、継承も extends で簡潔に書けます。

JavaScript:class構文
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  greet() {
    return `こんにちは、${this.name}です`;
  }
}

const p = new Person("Alice", 25);
console.log(p.greet());
JavaScript:継承(extends / super)
class Student extends Person {
  constructor(name, age, school) {
    super(name, age);   // 親のコンストラクタを呼ぶ
    this.school = school;
  }
  greet() {
    return `${super.greet()}(${this.school})`;
  }
}

const s = new Student("Bob", 20, "A大学");
console.log(s.greet()); // "こんにちは、Bobです(A大学)"

型を付けてより安全に書きたい場合は、TypeScriptのクラスの型定義 完全ガイドも参考になります(アクセス修飾子や抽象クラスまで解説)。

instanceof と new.target

あるオブジェクトが特定のクラス(コンストラクタ)から作られたかは instanceof で判定します。new.target を使うと、関数が new 付きで呼ばれたかを検知できます。

JavaScript:instanceof と new.target
console.log(p instanceof Person);  // true
console.log(s instanceof Person);  // true(継承元もtrue)

// new を忘れたら例外にする
function Foo() {
  if (!new.target) {
    throw new Error("new を付けて呼んでください");
  }
}

newを使わずにオブジェクトを作る

1つだけのオブジェクトや、継承が不要な場合は new を使わない方法も便利です。

JavaScript:リテラル / Object.create / ファクトリ
// ① オブジェクトリテラル(最も手軽)
const obj = { name: "Alice", greet() { return `Hi ${this.name}`; } };

// ② Object.create(プロトタイプを指定して作る)
const proto = { greet() { return "hi"; } };
const o = Object.create(proto);

// ③ ファクトリ関数(newなしでオブジェクトを返す)
function createPerson(name) {
  return { name, greet() { return `Hi ${this.name}`; } };
}
const person = createPerson("Alice");

生成したオブジェクトを配列にまとめて処理する場面では、map・filter・reduceの使い方配列から条件に合う要素を取り出す方法が役立ちます。

newを忘れたときの落とし穴

コンストラクタ関数でnewを忘れると危険:new なしでコンストラクタ関数を呼ぶと、this が新オブジェクトに束縛されません。strictモードでは thisundefined になりエラー、非strictでは globalThis を汚染してしまいます。
JavaScript:new忘れの挙動
function Person(name) {
  this.name = name;
}

// NG: new を忘れた
const p = Person("Alice"); // strictモードでは TypeError(this が undefined)

// class なら new 忘れは即 TypeError で気づける(安全)
class Animal {}
Animal(); // TypeError: Class constructor Animal cannot be invoked without 'new'

この点でも、new 忘れを TypeError で防げる class の方が安全です。

よくある質問(FAQ)

QJavaScriptのnew演算子は何をするものですか?
Aコンストラクタ関数や class をインスタンス化します。「空オブジェクト作成 → prototype リンク → コンストラクタ実行 → インスタンス返却」の順で処理されます。
Qnewを使わずにオブジェクトを作る方法は?
Aオブジェクトリテラル {}Object.create()、ファクトリ関数(通常の関数でオブジェクトを返す)が使えます。class より軽量で、カプセル化しやすいファクトリパターンも有用です。
Qnew演算子を忘れた場合に何が起こりますか?
Aコンストラクタ関数が通常の関数として実行され、this がグローバルオブジェクトを指します(strictモードでは undefined になりエラー)。classnew 無しで呼ぶと TypeError になるため、より安全です。
Qコンストラクタ関数とclassの違いは?
Aどちらも new でインスタンスを作りますが、class はメソッド定義や継承(extends / super)が分かりやすく、new 忘れを防げます。現代のJavaScriptでは class が標準です。

まとめ

new 演算子は、コンストラクタや class から新しいオブジェクトを生成します。内部では「空オブジェクト → prototype リンク → this 束縛 → 返却」が行われ、共通メソッドは prototype に置くことで全インスタンスで共有されます。

現代のJavaScriptでは class 構文が標準で、継承も簡潔に書け、new 忘れを TypeError で防げます。1つだけのオブジェクトや継承が不要な場合は、リテラルやファクトリ関数も検討しましょう。