JavaScriptでは、__proto__プロパティを使って、オブジェクトが持つプロトタイプにアクセスすることができます。
プロトタイプを確認するだけであれば__proto__は便利ですが、実際には古い方法であり非推奨となっています。

現在では__proto__の代わりとなるメソッドが用意されています。
そこで今回は、プロトタイプの確認や設定のためのメソッドについて解説していきます。

Object.create()

Object.createメソッドは、既存のオブジェクトをプロトタイプとして継承し、新しいオブジェクトを作成します。

第一引数に指定したprototypeオブジェクトを継承します。

Object.create(prototype);

オブジェクトリテラルでオブジェクトを作成すると、同時にObject.prototypeを継承します。これをObject.createメソッドで書くと次のようになります。

// let obj = {} と同じ
let obj = Object.create(Object.prototype);

もちろんtoStringなどのObject.prototypeに用意されているメソッドも使用できます。
そのため、以下は同じものとして見なされます。

let obj = Object.create(Object.prototype);

console.log(obj.toString === Object.prototype.toString); // true

例えば、userという名前のObjectがあるとします。
userをプロトタイプとして、新しいuser1というオブジェクトを作成するとこのように書くことができます。

let user = {
  id: true
};

// userをプロトタイプとして新しいオブジェクトを作成
let user1 = Object.create(user);

console.log(user1.id); // true

また、Object.createメソッドは、任意で第二引数を指定することができます。
新しいオブジェクトにプロパティを追加したい際に記述します。

Object.create(prototype[, descriptors]);

では、user1に追加のプロパティを指定してみましょう。

let user = {
  id: true
};

// 新しいオブジェクト作成時にプロパティを追加
let user1 = Object.create(user, {
  age: {
    value: 20
  }
});

console.log(user1.age); // 20

userには無かったageというプロパティを追加することができました。

Object.prototypeを継承しない

Objectは、インスタンス作成時にObject.prototypeを継承します。
しかし、継承したくない場合にはどうしたら良いのでしょうか?

そのような場合、Object.create(null)で、プロパティやメソッドを持たない空のオブジェクトを作成することができます。

let obj = Object.create(null);

console.log(obj.hasOwnProperty); // undefined

objは、Object.prototypeを継承していないため、そのプロトタイプメソッドであるhasOwnPropertyを呼び出すことができません。

代わりに、ES2022から導入されたObject.hasOwnメソッドが使えます。対象のオブジェクトがObject.prototypeを継承しなくても有効です。

let obj = Object.create(null);

console.log(Object.hasOwn(obj)); // false

これでobjは、プロパティを持っていない空のオブジェクトであることが確認できます。

Object.getPrototypeOf()

Object.getPrototypeOfメソッドは、オブジェクトのプロトタイプを取得します。

引数にオブジェクトを指定すると、そのオブジェクトのプロトタイプが返ります。

Object.getPrototypeOf(obj);

では、先ほど作成したuser1のプロトタイプを確認してみましょう。

let user = {
  id: true
};

let user1 = Object.create(user);

// user1はuserのプロトタイプを継承している
console.log(Object.getPrototypeOf(user1)); // { id: true }
console.log(Object.getPrototypeOf(user1) === user); // true

user1userの値を参照している(と同じ)であることが確認できます。

Object.setPrototypeOf()

Object.setPrototypeOfメソッドは、オブジェクトのプロトタイプを設定します。

第一引数にオブジェクト、第二引数に設定したいプロトタイプを指定します。

Object.getPrototypeOf(obj, prototype);

ここでは、user1に対して、新たにプロトタイプを設定してみましょう。
まずこの時点では、user1userが同じであることが確認できます。

let user = {
  id: true
};

let user1 = Object.create(user);

// user1はuserのプロトタイプを継承している
console.log(Object.getPrototypeOf(user1) === user); // true

では、第一引数にuser1、第二引数にuser_newを設定して、user1のプロトタイプを変更してみます。

let user_new = {
  age: 20
};

// user1のプロトタイプをuser_newに変更
Object.setPrototypeOf(user1, user_new);

console.log(Object.getPrototypeOf(user1) === user_new); // true

このように、user1のプロトタイプがuser_newに変更されていることが分かります。

そのため、継承元であったuserとは別のものとなります。

console.log(Object.getPrototypeOf(user1) === user); // false

まとめ

今回は、プロトタイプの確認や設定を行うためのメソッドについて解説しました。

// ポイント
* Object.create():既存のオブジェクトをプロトタイプとして継承して新しいオブジェクトを作成する
* Object.create(null):Object.prototypeを継承しないオブジェクトを作成する
* Object.getPrototypeOf():オブジェクトのプロトタイプを取得する
* Object.setPrototypeOf():オブジェクトのプロトタイプを設定する

合わせて読みたいプロトタイプシリーズ

第1回:プロトタイプの仕組み
第2回:オブジェクトとプロトタイプ継承
第3回:プロトタイプとメソッド(当記事)